1
0
This repository has been archived on 2022-11-26. You can view files and clone it, but cannot push or open issues or pull requests.

2325 lines
77 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*************************************/
//Хранит информацию о пользователях во время работы бота
var users_keys = new Map();
//Некие константы
var config = require('./config');
/**
* Ждать ms милисекунд.
*
* @param {number} ms Количество милисекунд ожидания.
*/
const DEF_DELAY = 1000;
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms || DEF_DELAY));
}
/*************************************/
//Запуск получения сообщений от телеграмм бота
var Bot = require('node-telegram-bot-api');
var bot = new Bot(process.env.TOKEN, { polling: true });
//Ошибки от телеграмма
bot.on('polling_error', (error) => {
console.log('Ошибка polling:', error);
});
//Авторизация в вк
const easyvk = require('easyvk');
var vk;
init();
async function init(){
vk = await easyvk({
token : process.env.VK_TOKEN
})
}
console.log('Бот был запущен');
/**
* Получение конфигурации для прикрепления кнопок к сообщению в телеграмм.
*
* @param {array} buttons Массив с необходимыми кнопками для сообщения.
* @param {number} id Id профиля telegram.
*/
function getButtonsByNames(buttons,id){
var returned_buttons = [];
if(buttons.includes('auth'))
returned_buttons.push([{ text: 'Авторизоваться', url: spotifyApi.createAuthorizeURL(config.scopes,id,true) }]);
//if(buttons.includes('logout'))
//returned_buttons.push([{ text: 'Выйти в браузере', url: 'https://www.spotify.com/ru/logout' }]);
//если авторизован
if(buttons.includes('profile_menu'))
returned_buttons.push([{ text: 'Профиль',
callback_data: JSON.stringify({command:"menu_profile"}) }]);
if(buttons.includes('profile'))
returned_buttons.push([{ text: 'Профиль пользователя',
callback_data: JSON.stringify({command:"as_message",message:"/info"}) }]);
if(buttons.includes('top_tracks'))
returned_buttons.push([{ text: 'Топ треков',
callback_data: JSON.stringify({command:"as_message",message:"/top_tracks"}) }]);
if(buttons.includes('top_artists'))
returned_buttons.push([{ text: 'Топ исполнителей',
callback_data: JSON.stringify({command:"as_message",message:"/top_artists"}) }]);
if(buttons.includes('player_menu'))
returned_buttons.push([{ text: 'Сейчас играет',
callback_data: JSON.stringify({command:"menu_player"}) }]);
// callback_data: JSON.stringify({command:"as_message",message:"/remote_control"}) }]);
/* if(buttons.includes('remote_control'))
returned_buttons.push([
{ text: '<', callback_data: JSON.stringify({command:"previous_track"}) },
{ text: '||', callback_data: JSON.stringify({command:"play_pause"}) },
{ text: '>', callback_data: JSON.stringify({command:"next_track"}) }]);*/
if(buttons.includes('download_track'))
returned_buttons.push([{ text: 'Скачать текущий трек',
callback_data: JSON.stringify({command:"download_track"}) }]);
if(buttons.includes('create_playlist'))
returned_buttons.push([{ text: 'Создать плейлист',
callback_data: JSON.stringify({command:"menu_playlists"}) }]);
if(buttons.includes('vk_menu'))
returned_buttons.push([{ text: 'Импорт треков из VK',
callback_data: JSON.stringify({command:"menu_vk"}) }]);
if(buttons.includes('import_vk_profile'))
returned_buttons.push([{ text: 'Треки профиля из VK',
callback_data: JSON.stringify({command:"as_message",message:"/vk_to_playlist"}) }]);
if(buttons.includes('import_vk_playlist'))
returned_buttons.push([{ text: 'Треки плейлиста из VK',
callback_data: JSON.stringify({command:"as_message",message:"/vk_get_playlist"}) }]);
if(buttons.includes('settings'))
returned_buttons.push([{ text: 'Настройки',
callback_data: JSON.stringify({command:"menu_settings"}) }]);
if(buttons.includes('help'))
returned_buttons.push([{ text: 'Список доступных комманд',
callback_data: JSON.stringify({command:"as_message",message:"/help"}) }]);
if(buttons.includes('create_playlist_from_liked'))
returned_buttons.push([{ text: 'Все избранные треки',
callback_data: JSON.stringify({command:"as_message",message:"/save_to_playlist"}) }]);
if(buttons.includes('create_dance_playlist_from_liked'))
returned_buttons.push([{ text: 'Избранные танцевальные треки',
callback_data: JSON.stringify({command:"as_message",message:"/save_dance_to_playlist"}) }]);
if(buttons.includes('create_not_russian_playlist_from_liked'))
returned_buttons.push([{ text: 'Избранные зарубежные треки',
callback_data: JSON.stringify({command:"as_message",message:"/save_english_to_playlist"}) }]);
let map = new Map();map.set(true,'Вкл.');map.set(false,'Выкл.');
if(buttons.includes('filter_explicit'))
returned_buttons.push([{ text: `Только песни без мата: ${map.get(users_keys.get(id).only_not_explicit)}`,
callback_data: JSON.stringify({command:"change_filter_explicit"}) }]);
if(buttons.includes('filter_popular'))
returned_buttons.push([{ text: `Только популярные песни: ${map.get(users_keys.get(id).only_popular)}`,
callback_data: JSON.stringify({command:"change_filter_popular"}) }]);
if(buttons.includes('logout'))
returned_buttons.push([{ text: 'Выйти из профиля Spotify',
callback_data: JSON.stringify({command:"as_message",message:"/logout"}) }]);
if(buttons.includes('main_menu'))
returned_buttons.push([{ text: 'Вернуться в главное меню',
callback_data: JSON.stringify({command:"menu_main"}) }]);
return returned_buttons;
}
/**
* Запуск функций для разных комманд из telegram.
*
* @param {map} data Информация о пользователе и его команда.
*/
async function launchFunctionByName(data){
switch(data.name){
case 'login':
var answer = await command_login(data);
return answer;
break;
case 'server_login':
var answer = await command_server_login(data);
return answer;
break;
case 'help':
var answer = await command_help(data);
return answer;
break;
case 'info_about_user':
var answer = await command_info_about_user(data);
return answer;
break;
case 'user_tracks':
var answer = await command_user_tracks(data);
return answer;
break;
case 'top_tracks':
var answer = await command_top_tracks(data);
return answer;
break;
case 'top_artists':
var answer = await command_top_artists(data);
return answer;
break;
case 'remote_control':
var answer = await command_remote_control(data);
return answer;
break;
case 'create_playlist_from_liked':
var answ = await command_get_liked(data);
var new_message = {
id: data.id,
type: 'create_playlist',
save_playlist: answ.save_playlist,
name: config.defaulttext.playlist_create.playlist_name,
description: config.defaulttext.playlist_create.playlist_description.replace('&{name}',answ.display_name),
track_array: answ.track_array,
bot_options: answ.bot_options,
quite:data.quite
}
messages_wait_Spotify_server.push(new_message);
return 'no_answer';
break;
case 'create_english_playlist_from_liked':
var answ = await command_get_liked(data);
var new_message = {
id: data.id,
type: 'get_english_tracks',
name: config.defaulttext.playlist_create.playlist_name_not_russian,
description: config.defaulttext.playlist_create.playlist_description_not_russian.replace('&{name}',answ.display_name),
track_array: answ.track_array,
bot_options: answ.bot_options
}
messages_wait_Spotify_server.push(new_message);
return 'no_answer';
break;
case 'create_dance_playlist_from_liked':
var answ = await command_get_liked(data);
var new_message = {
id: data.id,
type: 'get_dance_tracks',
name: config.defaulttext.playlist_create.playlist_name_dance,
description: config.defaulttext.playlist_create.playlist_description_dance.replace('&{name}',answ.display_name),
// audios: answ.audios,
track_array: answ.track_array,
bot_options: answ.bot_options
}
//console.log(new_message);
messages_wait_Spotify_server.push(new_message);
return 'no_answer';
break;
case 'create_not_explicit_playlist_from_liked':
var answ = await command_get_liked(data);
var new_message = {
id: data.id,
type: 'get_not_explicit_tracks',
name: config.defaulttext.playlist_create.playlist_name_not_explicit,
description: config.defaulttext.playlist_create.playlist_description_not_explicit.replace('&{name}',answ.display_name),
track_array: answ.track_array,
bot_options: answ.bot_options
}
messages_wait_Spotify_server.push(new_message);
return 'no_answer';
break;
case 'logout':
var answer = await command_logout(data);
return answer;
break;
case 'show_list_of_users':
var answer = await command_show_list_of_users(data);
return answer;
break;
case 'update_all_liked':
var answer = await command_update_all_liked(data);
return answer;
break;
case 'get_info':
var answer = await command_get_info(data);
return answer;
break;
case 'create_playlist_from_vk':
var answer = await command_create_playlist_from_vk(data);
return answer;
break;
case 'create_playlist_from_vk_playlist':
var answer = await command_create_playlist_from_vk_playlist(data);
return answer;
break;
case 'create_playlist_in_vk':
var answ = await command_get_liked(data);
var new_message = {
id: data.id,
type: 'create_playlist_from_spotify',
name: config.defaulttext.playlist_create.playlist_name,
description: config.defaulttext.playlist_create.playlist_description.replace('&{name}',answ.display_name),
track_array: answ.track_array,
bot_options: answ.bot_options
}
//console.log(new_message);
messages_with_vk_server.push(new_message);
return 'no_answer';
break;
case 'create_playlist_from_yandex':
var answer = await command_get_liked_from_yandex(data);
return answer;
break;
case 'yandex_login':
var answer = await command_yandex_login(data);
return answer;
break;
case 'like_playlist':
var answ = await command_get_playlist(data);
await command_like_tracks(answ);
users_keys.get(data.id).is_waiting = false;
return 'no_answer';
break;
case 'download_track':
var new_message = {
id: data.id,
type: 'download_track',
text: data.text,
refreshToken: data.refreshToken,
options: data.options,
answer: data.answer
}
messages_wait_Spotify_server.push(new_message);
return 'no_answer';
/*var answer = await command_server_download_track(data);
return answer;*/
break;
case 'query':
var answer = await command_query(data);
return answer;
break;
default:
return data.answer;
break;
}
}
//Выполнить операцию с таблицей
async function command_query(data){
var answer = data.answer;
var client = await new Client({
connectionString: process.env.DATABASE_URL,
ssl: {
rejectUnauthorized: false
}
})
await client.connect()
.catch(e => {
console.error(e);
})
try {
answer += JSON.stringify(await client.query(data.text)).replace(/{/g,'{\n').replace(/}/g,'\n}').replace(/,/g,',\n')
await client.end();
}
catch(e){
console.error(e);
await client.end();
};
return answer;
}
//Отправить сообщение с ссылкой для авторизации
async function command_login(data){
var answer = data.answer;
return answer.replace('&{url}', spotifyApi.createAuthorizeURL(config.scopes,data.id,true));
}
//Отправить сообщение со списком всех доступных комманд
function command_help(data){
var answer = data.answer;
config.commands.forEach(function (values,keys) {
if(values.have_description)
if((values.need_admin==data.is_Admin)||(!values.need_admin))
if((values.need_auth==data.is_Auth)||(values.show_after_login&&data.is_Auth))
answer += `\n ${keys} - ${values.description}`;
});
if(data.is_Admin){
answer += `\n----------------------`;
config.admin_commands.forEach(function (values,keys) {
if(values.have_description)
if((values.need_auth==data.is_Auth)||(values.show_after_login&&data.is_Auth))
answer += `\n ${keys} - ${values.description}`;
});
}
return answer;
}
//Выйти из профиля
async function command_logout(data){
var del_user = `DELETE FROM USERS WHERE id = ${data.id};`;
await client.query(del_user)
users_keys.get(data.id).refreshToken = 'unauthorized';
return data.answer;
}
//Получить информацию о текущем профиле
async function command_info_about_user(data){
var temp_spotifyApi = await getUserByRefreshToken(data.refreshToken,data.options);
var answer = data.answer;
const me = await temp_spotifyApi.getMe();
var current_song = await temp_spotifyApi.getMyCurrentPlayingTrack()
.then(function(data) {
if(data.body.item){
var song = data.body.item.name + ' - ';
for (const artist of data.body.item.artists)
song += artist.name + ', ';
return song.substring(0,song.length-2);
}
else return false;
}, function(err) {
return false;
});
if(current_song) answer +='\n<b>Сейчас играет</b>: ' + current_song;
const music = await temp_spotifyApi.getMySavedTracks({
limit : 1,
offset: 0
});
return answer.replace('&{name}',me.body.display_name)
.replace('&{email}',me.body.email)
.replace('&{followers}',me.body.followers.total)
.replace('&{total}',music.body.total);
}
//Получить 20 последних добавленных треков
async function command_user_tracks(data){
var temp_spotifyApi = await getUserByRefreshToken(data.refreshToken,data.options);
var answer = data.answer;
const music = await temp_spotifyApi.getMySavedTracks({
limit : 20,
offset: 0
});
for(var i=0; i<music.body.items.length;i++){
answer += "\n● " + music.body.items[i].track.name + " - " + music.body.items[i].track.artists[0].name;
for(var j=1; j<music.body.items[i].track.artists.length;j++) {
answer += ", " + music.body.items[i].track.artists[j].name;
}
}
return answer;
}
//Список треков на повторе
async function command_top_tracks(data){
var temp_spotifyApi = await getUserByRefreshToken(data.refreshToken,data.options);
var answer = data.answer;
const music = await temp_spotifyApi.getMyTopTracks();
for(var i=0; i<music.body.items.length;i++){
answer += "\n● " + music.body.items[i].name + " - " + music.body.items[i].artists[0].name;
for(var j=1; j<music.body.items[i].artists.length;j++) {
answer += ", " + music.body.items[i].artists[j].name;
}
}
return answer;
}
//Артисты на повторе
async function command_top_artists(data){
var temp_spotifyApi = await getUserByRefreshToken(data.refreshToken,data.options);
var answer = data.answer;
const music = await temp_spotifyApi.getMyTopArtists();
for(var i=0; i<music.body.items.length;i++){
answer += "\n● " + music.body.items[i].name;
}
return answer;
}
//Управление музыкой
async function command_remote_control(data){
var temp_spotifyApi = await getUserByRefreshToken(data.refreshToken,data.options);
var answer = data.answer;
var current_song = await temp_spotifyApi.getMyCurrentPlayingTrack()
.then(function(data) {
if(data.body.item){
var song = data.body.item.name + ' ● ';
for (const artist of data.body.item.artists)
song += artist.name + ', ';
return song.substring(0,song.length-2);
}
else return false;
}, function(err) {
return false;
});
answer = answer.replace('&{track_name}',current_song)||`В данный момент воспроизведение не запущено`;
if(data.msg){
bot.editMessageText(answer,data.msg)
users_keys.get(data.id).is_waiting = false;
return 'no_answer'
}
return answer;
}
//Получить избранные треки с серверов Spotify, при ошибке повторяется запрос
async function spotify_getMySavedTracks(limit,offset,temp_spotifyApi){
try{
const ans = await temp_spotifyApi.getMySavedTracks({
limit : limit,
offset: offset
});
return ans;
} catch (e) {
await sleep(100);
return await spotify_getMySavedTracks(limit,offset,temp_spotifyApi);
}
}
async function command_get_liked(data){
var temp_spotifyApi = await getUserByRefreshToken(data.refreshToken,data.options);
const user = await temp_spotifyApi.getMe();
let only_not_explicit = users_keys.get(data.id).only_not_explicit;
let only_popular = users_keys.get(data.id).only_popular;
var save_playlist = !(only_not_explicit||only_popular);
var music = await spotify_getMySavedTracks(1,0,temp_spotifyApi);
var limit = 50;
var total = music.body.total;
var offset = 0;
var track_array = [];
if(total==0)
return config.defaulttext.playlist_create.empty_playlist;
var answer = config.defaulttext.playlist_create.playlist_created;
var msg = {};
if(data.quite === undefined)
msg = await bot.sendMessage(data.id, answer, { reply_markup : JSON.stringify({
inline_keyboard: [[ {
text: config.defaulttext.playlist_create.process_started.replace('&{total}',total),
callback_data: JSON.stringify({command:"waiting"})
} ]]
})});
while (offset < total){
music = await spotify_getMySavedTracks(limit,offset,temp_spotifyApi);
for(var i=0; i<music.body.items.length;i++){
let track = music.body.items[i].track;
let artists = [];
for (const artist of track.artists)
artists.push({id:artist.id,name:artist.name})
let track_info = {
id:track.id,
uri:track.uri,
name:track.name,
artists:artists
};
if(!(only_not_explicit&&track.explicit)&&!(only_popular&&track.popularity<40))
await track_array.push(track_info);
}
if(data.quite === undefined)
await bot.editMessageText(answer ,{
chat_id: msg.chat.id,
message_id : msg.message_id,
reply_markup : JSON.stringify({ inline_keyboard: [[ {
text: config.defaulttext.playlist_create.in_process.replace('&{offset}',offset).replace('&{total}',total),
callback_data: JSON.stringify({command:"waiting"})
} ]] })
});
offset = offset + limit;
}
var bot_options = {}
if(data.quite === undefined) bot_options = {
chat_id: msg.chat.id,
message_id : msg.message_id,
reply_markup : JSON.stringify({ inline_keyboard: [] })
}
var answ = {
save_playlist: save_playlist,
track_array: track_array,
bot_options: bot_options,
display_name:user.body.display_name
}
return await answ;
}
async function command_show_list_of_users(data){
var answer = data.answer;
let count = 0;
for await (const key of users_keys) {
var refreshToken = key[1].refreshToken;
if(refreshToken != 'unauthorized'&&key[0]>0){
count++;
var temp_spotifyApi = await getUserByRefreshToken(refreshToken,data.options);
var user = await temp_spotifyApi.getMe();
answer += `\n<b>Пользователь:</b> <a href="tg://user?id=${key[0]}">${user.body.display_name}</a> `;
if(key[1].liked!=='nothing')
answer += `<a href="https://open.spotify.com/playlist/${key[1].liked}">💗</a>`;
if(key[0]==data.id) answer += ' (Вы)';
}
}
return answer.replace('&{count}',count);
}
var whitelist = [247608317,483162302,784291122,1239328626,955327894,374919212]
async function command_update_all_liked(data){
var answer = data.answer;
var command_info = config.commands.get('/save_to_playlist')||config.admin_commands.get('/save_to_playlist');
for await (const key of users_keys) {
if(key[1].refreshToken !== 'unauthorized'&&whitelist.includes(key[0]))
messages_wait_Spotify.push({
id : key[0],
command : '/save_to_playlist',
text : '',
command_info : command_info,
quite : true
});
}
return answer;
}
async function command_server_login(data){
var options = config.options.server_options;
var answer = "";
for await (const server of options){
var temp_spotifyApi = await new SpotifyWebApi(server);
answer += await data.answer.replace('&{url}', temp_spotifyApi.createAuthorizeURL(config.scopes,encodeURI(JSON.stringify(server)),true));
}
return answer;
}
const got = require('got');
const PastebinAPI = require('pastebin-ts');
const pastebin = new PastebinAPI({
'api_dev_key' : process.env.PASTEBIN_API_TOKEN
});
async function spotify_addTracksToPlaylist(tracks,playlist_id,temp_spotifyApi,track_index){
try{
let ans = await temp_spotifyApi.addTracksToPlaylist(playlist_id, tracks, { position : track_index });
return ans;
} catch (e) {
await sleep(100);
//console.log(e);
return await spotify_addTracksToPlaylist(tracks,playlist_id,temp_spotifyApi,track_index);
}
}
async function command_create_playlist(data){
data.temp_spotifyApi = await getUserByRefreshToken(data.options.refreshToken,data.options);
if(data.save_playlist){
if(users_keys.get(data.id).liked == 'nothing'){
data.playlist_id = (await data.temp_spotifyApi.createPlaylist(data.name, { 'description': data.description, 'public': false })).body.id
users_keys.get(data.id).liked=data.playlist_id;
update_users.set(data.id);
}
else {
data.playlist_id = users_keys.get(data.id).liked;
data = await command_update_playlist(data);
}
}
else data.playlist_id = (await data.temp_spotifyApi.createPlaylist(data.name, { 'description': data.description, 'public': false })).body.id
var answer = config.defaulttext.playlist_created;
if(data.quite === undefined)
await bot.editMessageText(answer, data.bot_options);
await command_add_tracks_to_playlist(data);
return;
}
async function command_update_playlist(data){
data.text = 'spotifyplaylist/' + data.playlist_id;
var tracks_in_playlist = await command_get_playlist(data);
var track_array = [];
for await(var track1 of data.track_array){
var isin = true;
for await(var track2 of tracks_in_playlist.track_array)
if(track1.id == track2.id)
isin = false;
if(isin) track_array.push(track1);
}
data.track_array = track_array;
return data;
}
async function command_add_tracks_to_playlist(data){
let tracks_array = [];
let track_index = 0;
while(data.track_array.length>0){
let track = data.track_array.shift();
await tracks_array.push(track.uri);
if(tracks_array.length==50||data.track_array.length==0){
await spotify_addTracksToPlaylist(tracks_array,data.playlist_id,data.temp_spotifyApi,track_index)
track_index+=tracks_array.length;
tracks_array = [];
}
}
if(data.quite === undefined){
var reply = JSON.parse(data.bot_options.reply_markup);
reply.inline_keyboard.push([ {
text: config.defaulttext.playlist_save,
callback_data: JSON.stringify({ command: "addP", p_id: data.playlist_id})
} ]);
data.bot_options.parse_mode = 'HTML';
data.bot_options.reply_markup = JSON.stringify(reply);
answer = config.defaulttext.playlist_done.replace('&{playlist_id}',data.playlist_id);
await bot.editMessageText(answer, data.bot_options);
}
return;
}
async function command_addPlaylistToUser(data){
var refreshToken = users_keys.get(data.id).refreshToken;
var temp_spotifyApi = await getUserByRefreshToken(refreshToken,data.options);
await temp_spotifyApi.followPlaylist(data.playlist_id,{'public' : true});
await bot.answerCallbackQuery(data.msg_id,'Плейлист успешно добавлен');
return;
}
async function spotify_search(find,temp_spotifyApi,number){
try{
const ans = await temp_spotifyApi.searchTracks(find,{
limit : number||1
});
return ans;
} catch (e) {
await sleep(100);
console.log(e);
return await spotify_search(find,temp_spotifyApi,number);
}
}
async function server_command_search_from_vk(data){
var answer = config.defaulttext.playlist_vk_create.playlist_in_process;
await bot.editMessageText(answer ,{
chat_id: data.id,
message_id : data.message_id,
});
var audios = data.audios;
var temp_spotifyApi = await getUserByRefreshToken(data.options.refreshToken,data.options);
var done = 0;
var errors = 0;
var error_list = "Не удалось найти следующие треки:\n";
var total = audios.length;
var track_array = [];
var bot_options;
while (audios.length>0) {
let audio = audios.shift();
var find_ = `${audio.artist} ${audio.title}`
.replace(/ x /g,' ')
.replace(/(\[.*?\])/g, '')
.trim().split(/(\(.*?\))/g);
var find = '';
for await(const temp of find_)
if(!temp.toLowerCase().startsWith('(prod.')&&!temp.toLowerCase().startsWith('(feat.'))
find+=temp;
find = find.replace(/feat./g,'');
const ans = await spotify_search(find,temp_spotifyApi);
if(ans.body.tracks.total>0){
done++;
let track = ans.body.tracks.items[0];
let artists = [];
for (const artist of track.artists)
artists.push({id:artist.id,name:artist.name})
let track_info = {
id:track.id,
uri:track.uri,
name:track.name,
artists:artists
};
await track_array.push(track_info);
if(done%50==0){
bot_options = {
chat_id: data.id,
message_id : data.message_id,
reply_markup : JSON.stringify({ inline_keyboard: [[ {
text: config.defaulttext.playlist_vk_create.in_process.replace('&{done}',done).replace('&{total}',total).replace('&{errors}',errors),
callback_data: JSON.stringify({command:"waiting"})
} ]] })
}
await bot.editMessageText(answer ,bot_options);
}
}
else{
errors++;
error_list+=`${audio.title} | ${audio.artist}\n`
}
await sleep(10);
}
var url;
await pastebin.createPaste({
text: error_list,
title: data.name + "(не нашлись треки)",
format: null,
privacy: 1,
expiration: '10M'
})
.then((data) => {
url = data;
})
.catch((err) => {
url = 'https://pastebin.com/XyBBXxLB';
});
bot_options = {
chat_id: data.id,
message_id : data.message_id,
parse_mode: 'HTML',
reply_markup : JSON.stringify({ inline_keyboard: [[ {
text: config.defaulttext.playlist_vk_create.in_process.replace('&{done}',done).replace('&{total}',total).replace('&{errors}',errors),
url: url
} ]] })
}
await bot.editMessageText(answer ,bot_options);
var new_message = {
id: data.id,
type: 'create_playlist',
name: data.name,
description: data.description,
track_array: track_array,
bot_options: bot_options
}
messages_wait_Spotify_server.push(new_message);
return;
}
function AllVariants(arr, prepend) {
var i, version, el, result = [];
prepend = prepend || [];
if(arr.length === 1) return [arr];
for( i=0; i<arr.length; i++) {
if( arr.length === 2) {
result.push( prepend.concat( [arr[i], arr[(i+1)%2]] ));
} else {
version = arr.slice();
el = version.splice(i,1);
result = result.concat( AllVariants( version, prepend.concat(el)));
}
}
return result;
}
async function server_command_search_from_yandex(data){
var answer = config.defaulttext.playlist_vk_create.playlist_in_process;
await bot.editMessageText(answer ,{
chat_id: data.id,
message_id : data.message_id,
});
var audios = data.audios;
var temp_spotifyApi = await getUserByRefreshToken(data.options.refreshToken,data.options);
var done = 0;
var errors = 0;
var error_list = "Не удалось найти следующие треки:\n";
var total = audios.length;
var track_array = [];
var bot_options;
/*while (audios.length>0) {
let audio = audios.shift();
var find_ = `${audio.artist} ${audio.title}`
.replace(/ x /g,' ')
.replace(/(\[.*?\])/g, '')
.trim().split(/(\(.*?\))/g);
var find = '';
for await(const temp of find_)
if(!temp.toLowerCase().startsWith('(prod.')&&!temp.toLowerCase().startsWith('(feat.'))
find+=temp;
find = find.replace(/feat./g,'').replace(/ /gi,' ').replace(/ё/g,'е');
const ans = await spotify_search(find,temp_spotifyApi);
if(ans.body.tracks.total>0){
done++;
let track = ans.body.tracks.items[0];
let artists = [];
for (const artist of track.artists)
artists.push({id:artist.id,name:artist.name})
let track_info = {
id:track.id,
uri:track.uri,
name:track.name,
artists:artists
};
await track_array.push(track_info);
if(done%50==0){
bot_options = {
chat_id: data.id,
message_id : data.message_id,
reply_markup : JSON.stringify({ inline_keyboard: [[ {
text: config.defaulttext.playlist_vk_create.in_process.replace('&{done}',done).replace('&{total}',total).replace('&{errors}',errors),
callback_data: JSON.stringify({command:"waiting"})
} ]] })
}
await bot.editMessageText(answer ,bot_options);
}
}
else{
errors++;
error_list+=`${audio.title} | ${audio.artist}\n`
}
await sleep(10);
}
*/
while(audios.length>0){
let track = audios.shift();
let combinations = AllVariants(track.artists);
let ans = {body:{tracks:{total:0}}};
let track_name;
while ( combinations.length>0) {
let artists = combinations.shift();
artists = Array.from(artists, function (artist) {return artist.name} ).join(', ');
track.albums.push({title:''})
while(ans.body.tracks.total == 0 && track.albums.length>0){
let album = track.albums.shift();
track_name = artists.replace(/ & /gi,' ').replace(/ x /gi,' ')/*track_name.substring(0,track_name.length-2)*/ + ' ' + track.title + ' ' + album.title;
track_name = track_name.replace(/ /gi,' ').replace(/ё/g,'е')
ans = await spotify_search(track_name,temp_spotifyApi);
}
if(ans.body.tracks.total>0)break;
}
if(ans.body.tracks.total>0){
done++;
let track = ans.body.tracks.items[0];
await track_array.push(track);
if(done%50==0){
bot_options = {
chat_id: data.id,
message_id : data.message_id,
reply_markup : JSON.stringify({ inline_keyboard: [[ {
text: config.defaulttext.playlist_vk_create.in_process.replace('&{done}',done).replace('&{total}',total).replace('&{errors}',errors),
callback_data: JSON.stringify({command:"waiting"})
} ]] })
}
await bot.editMessageText(answer ,bot_options);
}
}
else{
errors++;
error_list+=`${track_name}\n`
}
}
var url;
await pastebin.createPaste({
text: error_list,
title: data.name + "(не нашлись треки)",
format: null,
privacy: 1,
expiration: '10M'
})
.then((data) => {
url = data;
})
.catch((err) => {
url = 'https://pastebin.com/XyBBXxLB';
});
bot_options = {
chat_id: data.id,
message_id : data.message_id,
parse_mode: 'HTML',
reply_markup : JSON.stringify({ inline_keyboard: [[ {
text: config.defaulttext.playlist_vk_create.in_process.replace('&{done}',done).replace('&{total}',total).replace('&{errors}',errors),
url: url
} ]] })
}
await bot.editMessageText(answer ,bot_options);
var new_message = {
id: data.id,
type: 'create_playlist',
name: data.name,
description: data.description,
track_array: track_array,
bot_options: bot_options
}
messages_wait_Spotify_server.push(new_message);
return;
}
async function haveRussianGenres(track,artist_genres){
let result = false;
if( track.name.search(/[А-яЁё]/) != -1 )
result = true;
for await (let artist of track.artists){
if( artist.name.search(/[А-яЁё]/) != -1 )
result = true;
let genres = artist_genres.get(artist.id);
if(genres.length==0) result = true;
else
for await (let genre of genres)
if(genre.includes('russian'))
result = true;
}
return result;
}
async function command_server_get_english_tracks(data){
//console.log(data);
var temp_spotifyApi = await getUserByRefreshToken(data.options.refreshToken,data.options);
let artists = [];
let artist_genres = new Map();
for await (let track of data.track_array)
for await (let artist of track.artists)
if(!artists.includes(artist.id))
await artists.push(artist.id);
let artist_array = [];
while(artists.length>0){
let artist = artists.shift();
artist_array.push(artist);
if(artist_array.length==50||artists.length==0){
let data = await temp_spotifyApi.getArtists(artist_array); /////////////////////////////////////////////////////////////////////
for (let art of data.body.artists)
artist_genres.set(art.id,art.genres);
artist_array = [];
}
}
let result_track_array = [];
for await (let track of data.track_array){
let isRussian = await haveRussianGenres(track,artist_genres);
if(!isRussian)
await result_track_array.push(track);
// console.log(track.name);
}
return result_track_array;
}
async function command_server_get_dance_tracks(data){
//console.log(data);
var temp_spotifyApi = await getUserByRefreshToken(data.options.refreshToken,data.options);
let result_track_array = [];
let tracks_array = [];
while(data.track_array.length>0){
let track = data.track_array.shift();
await tracks_array.push(track.id);
if(tracks_array.length==50||data.track_array.length==0){
let data = await temp_spotifyApi.getAudioFeaturesForTracks(tracks_array);//////////////////////////////////////////////////////////////////
// console.log(data);
for await (const track of data.body.audio_features) {
if(track!=null)
if(track.danceability>0.6)
if(track.valence>0.6) {
let track_info = {
id:track.id,
uri:track.uri
}
result_track_array.push(track_info);
}
}
tracks_array = [];
}
// console.log(data.track_array.length);
}
//console.log(result_track_array.length);
return result_track_array;
}
async function command_server_get_not_explicit_tracks(data){
let result_track_array = [];
while(data.track_array.length>0){
let track = data.track_array.shift();
if(!track.explicit)
await result_track_array.push(track);
}
return result_track_array;
}
const superagent = require('superagent');
async function command_create_playlist_from_vk(data){
await vk;
var name = 'Аудиозаписи пользователя'
var vk_id = data.text;
if(!vk_id)
return config.defaulttext.playlist_vk_create.rule;
if(vk_id.startsWith('vk.com/'))
vk_id = 'https://'+vk_id;
if(vk_id.startsWith('https://vk.com/')){
await vk.call("users.get",{
user_ids: vk_id.slice(15),
name_case: 'gen'
}).then(async (response) => {
vk_id = response[0].id;
name = config.defaulttext.playlist_vk_create.playlist_name.replace('&{last_name}',response[0].last_name).replace('&{first_name}',response[0].first_name)
}).catch(function(e) {
console.log(e.error_msg);
});
}
else
return config.defaulttext.playlist_vk_create.wrong_profile_url;
if(!(/^\d+$/.test(vk_id)))
return config.defaulttext.playlist_vk_create.wrong_id;
//console.log(name);
const msg = await bot.sendMessage(data.id, config.defaulttext.playlist_vk_create.playlist_vk_get);
var next_from = true;
var music_section = '';
var audios = [];
while(next_from){
await vk.call("execute",{
profile_id: vk_id,
next_from: next_from,
music_section: music_section,
code: `
var res = {};
var profile_id = Args.profile_id;
res.next_from = Args.next_from;
res.music_section = Args.music_section;
res.audios = [];
if (res.music_section == '') {
var audios = API.catalog.getAudio({url:'https://vk.com/audios'+profile_id,need_blocks:1});
res.music_section = audios.catalog.sections[0].id;
res.next_from = audios.catalog.sections[0].next_from;
if(res.next_from){
res.audios = audios.audios;
}
}
var i = 0;
while(res.next_from != null && i < 20){
var audios_info = API.catalog.getSection({start_from: res.next_from, section_id: res.music_section});
var audios = audios_info.audios;
if(audios!=null){
while(audios.length>0)
res.audios.push(audios.shift());
}
res.next_from = audios_info.section.next_from;
i = i + 1;
}
return res;`
}).then(async (response) => {
while (response.getFullResponse().response.audios.length>0)
await audios.push(response.getFullResponse().response.audios.shift());
next_from = response.getFullResponse().response.next_from;
music_section = response.getFullResponse().response.music_section;
bot_options = {
chat_id: data.id,
message_id : msg.message_id,
reply_markup : JSON.stringify({ inline_keyboard: [[ {
text: config.defaulttext.playlist_vk_create.vk_in_process.replace('&{done}',audios.length),
callback_data: JSON.stringify({command:"waiting"})
} ]] })
}
await bot.editMessageText(config.defaulttext.playlist_vk_create.playlist_vk_get ,bot_options);
}).catch(function(e) {
console.log(e.error_msg);
});
await sleep(1000);
}
var message = {
id: data.id,
message_id: msg.message_id,
type: 'search_from_vk',
name: name,
audios: audios,
description : config.defaulttext.playlist_vk_create.playlist_description_profile
}
messages_wait_Spotify_server.push(message);
return 'no_answer';
}
async function command_create_playlist_from_vk_playlist(data){
var name = 'Плейлист из вк'
var vk_url = data.text;
if(!vk_url)
return config.defaulttext.playlist_vk_create.playlist_rule;
if(vk_url.startsWith('vk.com/'))
vk_url = 'https://'+vk_url;
var user_id = 0;
var access_key;
if(vk_url.startsWith('https://vk.com/audios')){
vk_url = vk_url.slice(21).split('?');
user_id = vk_url.shift();
vk_url = ('vk'+vk_url[0]).split('audio_playlist')[1].split('%2F')
if(vk_url.length>1)
access_key = vk_url[1];
vk_url = vk_url[0].split('/')
if(vk_url.length>1)
access_key = vk_url[1];
vk_url = 'https://vk.com/music?z=audio_playlist'+vk_url[0]+'/'+access_key;
}
if(vk_url.startsWith('https://vk.com/music/playlist/'))
vk_url = 'https://vk.com/music?z=audio_playlist'+vk_url.slice(32);
if(!vk_url.startsWith('https://vk.com/music?z=audio_playlist'))
return config.defaulttext.playlist_vk_create.wrong_playlist_url;
vk_url = vk_url.slice(37).split('/');
access_key = vk_url[1];
vk_url = vk_url[0].split(/_+/g);
//console.log(vk_url,access_key);
if(vk_url.length>2) access_key = vk_url[2];
var owner_id = vk_url[0],playlist_id = vk_url[1],offset=0,count=1000,fields,total=1;
if(!((/^\d+$/.test(owner_id))&&(/^\d+$/.test(playlist_id))))
return config.defaulttext.playlist_vk_create.wrong_playlist_url;
const msg = await bot.sendMessage(data.id, config.defaulttext.playlist_vk_create.playlist_vk_get);
var first_name,last_name,description='';
var audios = [];
while(total>offset){
await vk.call("execute",{
v: '5.144',
user_id: user_id,
owner_id: owner_id,
playlist_id: playlist_id,
offset: offset,
access_key: access_key,
count: count,
fields: fields,
code: `
var user_id = Args.user_id;
var owner_id = Args.owner_id;
if(user_id == 0) user_id = owner_id;
var playlist_id = Args.playlist_id;
var access_key = Args.access_key;
var count = Args.count;
var offset = Args.offset;
var fields = Args.fields;
var res = {};
if (offset == 0) {
if(access_key == 'undefined'){
var playlists = API.catalog.getAudio({url:'https://vk.com/audios'+user_id,need_blocks:1}).playlists;
while(playlists.length>0){
var playlist = playlists.shift();
if(playlist.original.playlist_id == playlist_id && playlist.original.owner_id == owner_id)
access_key = playlist.original.access_key;
}
}
res.playlist = API.audio.getPlaylistById({
owner_id: owner_id,
playlist_id: playlist_id,
access_key: access_key,
ref: Args.ref
});
if (res.playlist.type == 0) {
if (owner_id < 0) {
res.owner = API.groups.getById({ group_id: -owner_id, fields: fields }).groups[0];
} else {
res.owner = API.users.get({ user_ids: owner_id, fields: fields })[0];
}
}
if (res.playlist.original != null) {
if (res.playlist.original.owner_id < 0) {
res.owner = API.groups.getById({ group_id: -res.playlist.original.owner_id, fields: fields }).groups[0];
} else {
res.owner = API.users.get({ user_ids: res.playlist.original.owner_id, fields: fields })[0];
}
}
}
res.audios = API.audio.get({ owner_id: owner_id, playlist_id: playlist_id, access_key: access_key, count: count, offset: offset, ref: Args.ref }).items;
return res;`
}).then(async (response) => {
//console.log(response)
//execute_errors = true;
if(response.getFullResponse().response.playlist){
name = response.getFullResponse().response.playlist.title;
total = response.getFullResponse().response.playlist.count;
description = response.getFullResponse().response.playlist.description;
access_key = response.getFullResponse().response.playlist.access_key;
playlist_id = response.getFullResponse().response.playlist.id;
owner_id = response.getFullResponse().response.playlist.owner_id;
}
if(response.getFullResponse().response.owner){
first_name = response.getFullResponse().response.owner.first_name;
last_name = response.getFullResponse().response.owner.last_name;
}
//console.log(response.getFullResponse())
offset = offset + count;
while(response.getFullResponse().response.audios.length>0)
audios.push(response.getFullResponse().response.audios.shift());
bot_options = {
chat_id: data.id,
message_id : msg.message_id,
reply_markup : JSON.stringify({ inline_keyboard: [[ {
text: config.defaulttext.playlist_vk_create.vk_in_process.replace('&{done}',audios.length),
callback_data: JSON.stringify({command:"waiting"})
} ]] })
}
if(response.getFullResponse().execute_errors)
await bot.editMessageText(config.defaulttext.playlist_vk_create.wrong_playlist_private,bot_options);
else await bot.editMessageText(config.defaulttext.playlist_vk_create.playlist_vk_get ,bot_options);
}).catch(function(e) {
console.log(e.error_msg);
});
await sleep(1000);
}
var message = {
id: data.id,
message_id: msg.message_id,
type: 'search_from_vk',
name: name,
audios: audios,
description : config.defaulttext.playlist_vk_create.playlist_description_playlist.replace('&{last_name}',last_name).replace('&{first_name}',first_name).replace('&{description)',description)
}
messages_wait_Spotify_server.push(message);
return 'no_answer';
}
const _yandex_config = {
CLIENT_ID: "23cabbbdc6cd418abb4b39c32c41195d",
CLIENT_SECRET: "53bc75238f0c4d08a118e51fe9203300",
AUTH_URL: "https://oauth.yandex.ru/token",
API_URL: "https://api.music.yandex.net:443"
}
async function command_yandex_login(data){
let credentials = data.text.split(" ");
try{
let auth_body = (await superagent
.post(_yandex_config.AUTH_URL)
.send(`grant_type=password&client_id=${_yandex_config.CLIENT_ID}&client_secret=${_yandex_config.CLIENT_SECRET}&username=${credentials[0]}&password=${credentials[1]}`)
.set('Content-Type', 'application/x-www-form-urlencoded')
).body;
users_keys.get(data.id).yandex = {
token: auth_body.access_token,
uid: auth_body.uid
}
console.log(users_keys.get(data.id));
return JSON.stringify(auth_body);
}
catch(e){
console.log(e);
return "Возникла ошибка при авторизации";
}
}
async function command_get_liked_from_yandex(data){
var name = 'Аудиозаписи яндекса';
try{
let tracks_body = (await superagent
.get(`${_yandex_config.API_URL}/users/${users_keys.get(data.id).yandex.uid}/likes/tracks?if-modified-since-revision=0`)
.set('Authorization', `OAuth ${users_keys.get(data.id).yandex.token}`)
).body.result;
let tracks_array = tracks_body.library.tracks;
let req = 'trackIds=';
while(tracks_array.length>0){
let track = tracks_array.shift();
req+= track.id+':'+track.albumId+',';
}
if(req!='trackIds=')req=req.substring(0,req.length-1);
let tracks_names = (await superagent
.post(`${_yandex_config.API_URL}/tracks?with-positions=true`)
.send(req)
.set('Authorization', `OAuth ${users_keys.get(data.id).yandex.token}`)
).body.result;
let audios = [];
while (tracks_names.length>0) {
let track = tracks_names.shift();
audios.push({title:track.title,artists:track.artists,albums:track.albums})
}
const msg = await bot.sendMessage(data.id, "Аудио из яндекса получены");
//console.log(tracks_body.library.tracks.length);
var message = {
id: data.id,
message_id: msg.message_id,
type: 'search_from_yandex',
name: name,
audios: audios,
description : "Аудио профиля яндекса:3"
}
messages_wait_Spotify_server.push(message);
return "no_answer";
}
catch(e){
console.log(e);
return "Возникла ошибка при получении избранных треков";
}
}
async function command_get_info(data){
answer = data.answer;
return answer;
}
async function get_vk_audio_id(track,i){
try {
return (await superagent.get(`https://i120.kissvk.com/api/song/search/do?query=${track}`)).body;
}
catch(e){
console.log('ошибочка');
await sleep(200)
if(i<10) {
return await get_vk_audio_id(track,i+1);
}
else return {songs:[]};
}
}
async function vk_command_create_playlist(data){
var audios = [];
for await (const track of data.track_array){
var track_name = '';
// console.log(track.artists);
for await (var artist of track.artists)
track_name += artist.name + ' ';
track_name += track.name;
audios.push(track_name)
}
await bot.editMessageText('Работает поиск треков в вк...',data.bot_options);
var audios_ids = [];
var i = 0;
while(audios.length > 0){
var track = audios.shift();
const body = await get_vk_audio_id(encodeURI(track),0)//(await superagent.get(`https://i120.kissvk.com/api/song/search/do?query=${track}`)).body;
if(body.songs.length>0)
audios_ids.push(body.songs[0].id);
// else console.log(track)
await sleep(100);
i++;
if(i%10 == 0){
data.bot_options.reply_markup = JSON.stringify({ inline_keyboard: [[ {
text: config.defaulttext.playlist_vk_create.vk_search_in_process.replace('&{done}',audios_ids.length).replace('&{errors}',i-audios_ids.length).replace('&{all}',i+audios.length),
callback_data: JSON.stringify({command:"waiting"})
} ]] })
await bot.editMessageText('Работает поиск треков в вк...',data.bot_options);
}
}
var playlist_id = -1;
var profile_id = -1;
var url = '';
await vk.call("execute",{
name: data.name,
description: data.description,
code: `var res = {};
var profile_id = API.users.get()[0].id;
res.playlist_id = API.audio.createPlaylist({owner_id: profile_id, title: Args.name, description: Args.description});
return res;`
}).then(async (response) => {
playlist_id = response.getFullResponse().response.playlist_id.id;
profile_id = response.getFullResponse().response.playlist_id.owner_id;
url = `https://vk.com/music/playlist/${profile_id}_${playlist_id}_${response.getFullResponse().response.playlist_id.access_key}`;
await bot.editMessageText(config.defaulttext.playlist_vk_create.vk_text_while_add_in_process,data.bot_options);
}).catch(function(e) {
console.log(e.error_msg);
});
i = 0;
var col = 0;
var tracks_to_add = [];
while(audios_ids.length>0)
{
tracks_to_add.push(audios_ids.shift());
i++;
if(i%50 == 0 || audios_ids.length == 0){
//console.log(tracks_to_add);
await vk.call("audio.addToPlaylist",{
audio_ids: tracks_to_add.join(','),
playlist_id: playlist_id,
owner_id: profile_id
}).then(async (response) => {
console.log(response)
data.bot_options.reply_markup = JSON.stringify({ inline_keyboard: [[ {
text: config.defaulttext.playlist_vk_create.vk_add_in_process.replace('&{done}',i),
callback_data: JSON.stringify({command:"waiting"})
} ]] })
col += tracks_to_add.length;
await bot.editMessageText(config.defaulttext.playlist_vk_create.vk_text_while_add_in_process,data.bot_options);
}).catch(function(e) {
console.log(e)
console.log(e.error_msg);
});
await sleep(1000);
tracks_to_add = [];
}
}
data.bot_options.reply_markup = JSON.stringify({ inline_keyboard: [[ {
text: config.defaulttext.playlist_vk_create.vk_add_in_process.replace('&{done}',col),
url: url
} ]] })
await bot.editMessageText(config.defaulttext.playlist_vk_create.playlist_full_created,data.bot_options);
console.log('закончил');
return ;
}
async function spotify_getPlaylistTracks(limit,offset,playlist_id,temp_spotifyApi){
try{
const ans = await temp_spotifyApi.getPlaylistTracks(playlist_id,{
limit : limit,
offset: offset
});
return ans;
} catch (e) {
await sleep(100);
return await spotify_getPlaylistTracks(limit,offset,playlist_id,temp_spotifyApi);
}
}
async function command_get_playlist(data){
var temp_spotifyApi = await getUserByRefreshToken(data.refreshToken||data.options.refreshToken,data.options);
let playlist_id = data.text.split('playlist/')[1].split('?').shift();
var music = await spotify_getPlaylistTracks(1,0,playlist_id,temp_spotifyApi);
var limit = 100;
var total = music.body.total;
var offset = 0;
var track_array = [];
if(total==0)
return config.defaulttext.playlist_create.empty_playlist;
var answer = config.defaulttext.playlist_create.playlist_get;
var msg;
if(data.quite === undefined) {
if(data.bot_options) msg = await bot.editMessageText(answer, data.bot_options)
else msg = await bot.sendMessage(data.id, answer, { reply_markup : JSON.stringify({
inline_keyboard: [[ {
text: config.defaulttext.playlist_create.process_started.replace('&{total}',total),
callback_data: JSON.stringify({command:"waiting"})
} ]]
})});
}
while (offset < total){
music = await spotify_getPlaylistTracks(limit,offset,playlist_id,temp_spotifyApi);
for(var i=0; i<music.body.items.length;i++){
let track = music.body.items[i].track;
let artists = [];
for (const artist of track.artists)
artists.push({id:artist.id,name:artist.name})
let track_info = {
id:track.id,
uri:track.uri,
name:track.name,
artists:artists
};
await track_array.push(track_info);
// console.log(track_info);
}
if(data.quite === undefined)
await bot.editMessageText(answer ,{
chat_id: msg.chat.id,
message_id : msg.message_id,
reply_markup : JSON.stringify({ inline_keyboard: [[ {
text: config.defaulttext.playlist_create.in_process.replace('&{offset}',offset).replace('&{total}',total),
callback_data: JSON.stringify({command:"waiting"})
} ]] })
});
offset = offset + limit;
}
var bot_options = {};
if(data.quite === undefined) bot_options = {
chat_id: msg.chat.id,
message_id : msg.message_id,
reply_markup : JSON.stringify({ inline_keyboard: [] })
}
var answ = {
options: data.options,
track_array: track_array,
bot_options: bot_options
}
return answ;
}
async function spotify_LikeTracks(tracks,temp_spotifyApi){
try{
const ans = await temp_spotifyApi.addToMySavedTracks(tracks);
return ans;
} catch (e) {
await sleep(100);
return await spotify_LikeTracks(tracks,temp_spotifyApi);
}
}
async function spotify_containsTracks(tracks,temp_spotifyApi){
try{
const ans = await temp_spotifyApi.containsMySavedTracks(tracks);
return ans;
} catch (e) {
await sleep(100);
return await spotify_containsTracks(tracks,temp_spotifyApi);
}
}
async function command_like_tracks(data){
var temp_spotifyApi = await getUserByRefreshToken(data.options.refreshToken,data.options);
var answer = 'Данные получены, ставлю лайки...';
await bot.editMessageText(answer, data.bot_options);
let track_array = [];
let tracks_array = [];
while(data.track_array.length>0){
let track = data.track_array.shift();
await tracks_array.push(track.id);
if(tracks_array.length==50||data.track_array.length==0){
var contains = await spotify_containsTracks(tracks_array,temp_spotifyApi)
for(var i = 0;i<tracks_array.length;i++)
if(!contains.body[i])
await track_array.push(tracks_array[i]);
tracks_array = [];
}
}
track_array.reverse();
while(track_array.length>0){
let track = track_array.shift();
await tracks_array.push(track);
if(tracks_array.length==50||track_array.length==0){
await spotify_LikeTracks(tracks_array,temp_spotifyApi);
tracks_array = [];
}
}
answer = 'Работа закончена';
bot.editMessageText(answer, data.bot_options);
return;
}
var music_ids = new Map();
async function command_server_get_track(data){
if(!data.text||data.text=="") return {err:`<b>Пустой поисковый запрос...</b>
Используйте /download [текст для поиска]
Например <code>/download Lida Лиза</code>`};
var temp_spotifyApi = await getUserByRefreshToken(data.options.refreshToken,data.options);
var answer = await spotify_search(data.text,temp_spotifyApi)
if(answer.body.tracks.total>0){
let track = answer.body.tracks.items[0];
return track;
}
else return {err:`Ничего не найдено`};
}
const SpotifyDownloadApi = require('spotifydl-core').default
async function command_server_download_track(data){
if(data.track.err) return await bot.sendMessage(data.id, data.track.err, {parse_mode: 'HTML'});
var track_name = '';
for await (var artist of data.track.artists)
track_name += artist.name + ', ';
track_name = track_name.substring(0,track_name.length-2) + ' - ' + data.track.name;
if(music_ids.get(data.track.id)) return await bot.sendDocument(data.id, music_ids.get(data.track.id))
let msg = await bot.sendMessage(data.id, `Трек найден: <b>${track_name}</b>
Происходит загрузка с серверов Spotify...`,{parse_mode: 'HTML'});
let spotify = new SpotifyDownloadApi(options);
let file = await spotify.downloadTrack(data.track.href);
let fileOptions = {
filename: `${data.track.name}.mp3`,
contentType: `audio/mpeg`,
};
await bot.editMessageText(`Трек найден: <b>${track_name}</b>
Загружаем в telegram...` ,{
chat_id: msg.chat.id,
message_id : msg.message_id,
parse_mode: 'HTML'
});
file = await bot.sendDocument(data.id, file, {}, fileOptions);
//console.log(file.audio);
music_ids.set(data.track.id,file.audio.file_id)
await bot.deleteMessage(msg.chat.id,msg.message_id);
return;
}
/******************--- answer_for_messages ----**************************/
var messages = [];
answer_for_messages();
var user_options = config.options.user_options;
var messages_wait_Spotify = [];
var messages_with_Spotify = [];
add_messages_with_Spotify();
answer_for_messages_with_Spotify();
var server_options = config.options.server_options;
var messages_wait_Spotify_server = [];
var messages_with_Spotify_server = [];
add_messages_with_Spotify_server();
answer_for_messages_with_Spotify_server();
var messages_with_vk_server = [];
answer_for_messages_with_vk_server();
async function answer_for_messages_with_vk_server(){
var message = messages_with_vk_server.shift();
while (message) {
var id = message.id;
try {
switch(message.type){
case 'create_playlist_from_spotify':
await vk_command_create_playlist(message);
console.log("создан плейлист вк");
break;
/* case 'create_playlist':
await command_create_playlist(message);
users_keys.get(id).is_waiting = false;
break;*/
}
} catch (e) {
console.log(e);
// users_keys.get(id).is_waiting = false;
}
users_keys.get(id).is_waiting = false;
message = messages_with_vk_server.shift();
}
setTimeout(answer_for_messages_with_vk_server, 100);
}
async function add_messages_with_Spotify_server(){
while((messages_wait_Spotify_server.length > 0) && (server_options.length > 0)){
var message = messages_wait_Spotify_server.shift();
var options = server_options.shift();
message.options = options;
await messages_with_Spotify_server.push(message);
}
setTimeout(add_messages_with_Spotify_server, 100);
}
async function answer_for_messages_with_Spotify_server(){
var message = messages_with_Spotify_server.shift();
while (message) {
(async () => {
var id = message.id;
var opt = message.options;
try {
let data;
switch(message.type){
case 'search_from_vk':
await server_command_search_from_vk(message);
break;
case 'search_from_yandex':
await server_command_search_from_yandex(message);
break;
case 'create_playlist':
await command_create_playlist(message);
break;
case 'get_english_tracks':
data = message;
message.track_array = await command_server_get_english_tracks(data);
await command_create_playlist(data);
break;
case 'get_dance_tracks':
data = message;
message.track_array = await command_server_get_dance_tracks(data);
await command_create_playlist(data);
break;
case 'get_not_explicit_tracks':
data = message;
message.track_array = await command_server_get_not_explicit_tracks(data);
await command_create_playlist(data);
break;
case 'download_track':
data = message;
data.track = await command_server_get_track(data);
await command_server_download_track(data);
break;
}
} catch (e) {
console.log(e);
users_keys.get(id).is_waiting = false;
}
server_options.push(opt);
users_keys.get(id).is_waiting = false;
})()
.catch(e => {
console.error(e);
});
message = messages_with_Spotify_server.shift();
}
setTimeout(answer_for_messages_with_Spotify_server, 100);
}
async function answer_for_messages(){
var message = messages.shift();
while (message) {
var data = {};
var id = message.id;
var command_info = message.command_info;
var answer = "";
var buttons = [];
var user_is_admin = (id == process.env.ADMIN_ID);
if(command_info.need_admin&&!user_is_admin)
answer = config.defaulttext.need_admin;
else {
var refreshToken = users_keys.get(id).refreshToken;
var user_is_auth = !(refreshToken == 'unauthorized');
if(command_info.need_auth&&!user_is_auth) {
answer = config.defaulttext.need_auth.answer;
buttons = getButtonsByNames(config.defaulttext.need_auth.buttons,id);
}
else {
if(command_info.another_after_login&&user_is_auth) {
answer = command_info.answer_after_login;
buttons = getButtonsByNames(command_info.buttons_after_login,id);
}
else {
answer = command_info.answer || 'no_answer';
buttons = getButtonsByNames(command_info.buttons,id);
if(command_info.function_name){
data = {
name : command_info.function_name,
id : id,
answer : answer,
is_Auth : user_is_auth,
is_Admin : user_is_admin,
refreshToken : refreshToken,
text : message.text,
msg : message.msg,
quite : message.quite
}
try {
users_keys.get(id).is_waiting = true;
answer = await launchFunctionByName(data);
} catch (e) {
console.log(e);
answer = 'Возникла ошибка';
users_keys.get(id).is_waiting = false;
}
}
}
}
}
message = messages.shift();
users_keys.get(id).is_waiting = false;
if(answer != 'no_answer'){
if (answer.length >= 4000)
while(answer.length>0&&data.quite === undefined){
await bot.sendMessage( id, answer.substring(0,4000), {
parse_mode: 'HTML',
reply_markup: {
inline_keyboard: buttons
}
});
answer = answer.substring(4000);
}
else if(data.quite === undefined)
bot.sendMessage( id, answer, {
parse_mode: 'HTML',
reply_markup: {
inline_keyboard: buttons
}
});
}
}
setTimeout(answer_for_messages, 100);
}
async function add_messages_with_Spotify(){
while((messages_wait_Spotify.length > 0) && (user_options.length > 0)){
var message = messages_wait_Spotify.shift();
var options = user_options.shift();
message.options = options;
//console.log(options);
await messages_with_Spotify.push(message);
}
setTimeout(add_messages_with_Spotify, 100);
}
async function answer_for_messages_with_Spotify(){
var message = messages_with_Spotify.shift();
while (message) {
var id = message.id;
var answer = "";
var buttons = [];
switch(message.type){
case 'add_playlist':
try {
await command_addPlaylistToUser(message);
} catch (e) {
console.log(e);
bot.answerCallbackQuery(message.msg_id,'Возникла ошибка при добавлении плейлиста');
}
users_keys.get(id).is_waiting = false;
break;
default:
var command_info = message.command_info;
var data = {};
var user_is_admin = (id == process.env.ADMIN_ID);
if(command_info.need_admin&&!user_is_admin)
answer = config.defaulttext.need_admin;
else {
var refreshToken = users_keys.get(id).refreshToken;
var user_is_auth = !(refreshToken == 'unauthorized');
if(command_info.need_auth&&!user_is_auth) {
answer = config.defaulttext.need_auth.answer;
buttons = getButtonsByNames(config.defaulttext.need_auth.buttons,id);
}
else {
if(command_info.another_after_login&&user_is_auth) {
answer = command_info.answer_after_login;
buttons = getButtonsByNames(command_info.buttons_after_login,id);
}
else {
answer = command_info.answer || 'no_answer';
buttons = getButtonsByNames(command_info.buttons,id);
if(command_info.function_name){
data = {
name : command_info.function_name,
id : id,
answer : answer,
is_Auth : user_is_auth,
is_Admin : user_is_admin,
refreshToken : refreshToken,
text : message.text,
options : message.options,
msg : message.msg,
quite : message.quite
}
if(message.msg) data.msg = message.msg;
try {
users_keys.get(id).is_waiting = true;
answer = await launchFunctionByName(data);
} catch (e) {
console.log(e);
answer = 'Возникла ошибка';
users_keys.get(id).is_waiting = false;
}
}
}
}
}
if(answer != 'no_answer'){
users_keys.get(id).is_waiting = false;
if (answer.length >= 4000)
while(answer.length>0&&data.quite === undefined){
await bot.sendMessage( id, answer.substring(0,4000), {
parse_mode: 'HTML',
reply_markup: {
inline_keyboard: buttons
}
});
answer = answer.substring(4000);
}
else if(data.quite === undefined)
bot.sendMessage( id, answer, {
parse_mode: 'HTML',
reply_markup: {
inline_keyboard: buttons
}
});
}
break;
}
user_options.push(message.options);
message = messages_with_Spotify.shift();
}
setTimeout(answer_for_messages_with_Spotify, 100);
}
/******************--- answer_for_messages ----**************************/
function start_answering(id,command,text){
if(!users_keys.get(id))
users_keys.set(id,{
refreshToken : 'unauthorized',
only_not_explicit : false,
only_popular : false,
is_waiting : false
});
if(!users_keys.get(id).is_waiting){
var command_info = config.commands.get(command)||config.admin_commands.get(command);
if(!command_info) {
bot.sendMessage( id, config.defaulttext.unknown);
}
else {
if(command_info.using_spotifyApi||command_info.need_auth)
messages_wait_Spotify.push({
id : id,
command : command,
text : text,
command_info : command_info
});
else
messages.push({
id : id,
command : command,
text : text,
command_info : command_info
});
}
}
else bot.sendMessage( id, config.defaulttext.need_wait);
}
/******************--- bot.onText ----**************************/
bot.onText(/^/, function (msg) {
//console.log(msg)
var id = msg.chat.id;
const args = msg.text.slice("/").trim().split(/ +/g);
const command = args.shift().toLowerCase();
var text = args.join(" ");
start_answering(id,command,text);
});
module.exports = bot;
/******************--- bot.onText ----**************************/
bot.on("callback_query", function(data){
//console.log(data);
const callbackId = data.id;
var chatId;
if(data.message) chatId = data.message.chat.id;
let callback_data = JSON.parse(data.data);
let buttons;
switch (callback_data.command) {
case "waiting":
// console.log(chatId);
bot.answerCallbackQuery(callbackId,'Ожидайте... Бот работает...'); //////////need_config_text
break;
case "addP":
messages_wait_Spotify.push({
id : chatId,
type : "add_playlist",
playlist_id : callback_data.p_id,
msg_id : callbackId
});
break;
case "download_track":
start_answering(chatId,'/download',data.message.text.substring(31).replace('●',''));
console.log(data.message.text.substring(31).replace('●',' - '));
bot.answerCallbackQuery(callbackId,'Выполнено!');
break;
case "as_message":
start_answering(chatId,callback_data.message);
bot.answerCallbackQuery(callbackId,'Выполнено!');
break;
case "menu_profile":
buttons = getButtonsByNames(config.defaulttext.buttons_profile_menu,chatId);
bot.editMessageText(config.defaulttext.menu_profile ,{
chat_id: chatId,
message_id : data.message.message_id,
parse_mode: 'HTML',
reply_markup : JSON.stringify({ inline_keyboard: buttons })
});
break;
case "menu_player":
buttons = getButtonsByNames(config.defaulttext.buttons_player_menu,chatId);
var command_info = config.commands.get('/remote_control')||config.admin_commands.get('/remote_control');
messages_wait_Spotify.push({
id : chatId,
command : 'remote_control',
text : '',
command_info : command_info,
msg : {
chat_id: chatId,
message_id : data.message.message_id,
parse_mode: 'HTML',
reply_markup : JSON.stringify({ inline_keyboard: buttons })
}
});
break;
case "menu_vk":
buttons = getButtonsByNames(config.defaulttext.buttons_vk_menu,chatId);
bot.editMessageText(config.defaulttext.menu_vk ,{
chat_id: chatId,
message_id : data.message.message_id,
parse_mode: 'HTML',
reply_markup : JSON.stringify({ inline_keyboard: buttons })
});
break;
case "menu_settings":
buttons = getButtonsByNames(config.defaulttext.buttons_settings_menu,chatId);
bot.editMessageText(config.defaulttext.menu_settings ,{
chat_id: chatId,
message_id : data.message.message_id,
parse_mode: 'HTML',
reply_markup : JSON.stringify({ inline_keyboard: buttons })
});
break;
case "menu_playlists":
buttons = getButtonsByNames(config.defaulttext.buttons_playlists_menu,chatId);
bot.editMessageText(config.defaulttext.menu_playlists ,{
chat_id: chatId,
message_id : data.message.message_id,
parse_mode: 'HTML',
reply_markup : JSON.stringify({ inline_keyboard: buttons })
});
break;
case "menu_main":
buttons = getButtonsByNames(config.defaulttext.buttons_main_menu,chatId);
bot.editMessageText(config.defaulttext.menu_main ,{
chat_id: chatId,
message_id : data.message.message_id,
parse_mode: 'HTML',
reply_markup : JSON.stringify({ inline_keyboard: buttons })
});
break;
case "change_filter_explicit":
users_keys.get(chatId).only_not_explicit=!users_keys.get(chatId).only_not_explicit;
buttons = getButtonsByNames(config.defaulttext.buttons_settings_menu,chatId);
bot.editMessageText(config.defaulttext.menu_settings ,{
chat_id: chatId,
message_id : data.message.message_id,
parse_mode: 'HTML',
reply_markup : JSON.stringify({ inline_keyboard: buttons })
});
update_users.set(chatId);
break;
case "change_filter_popular":
users_keys.get(chatId).only_popular=!users_keys.get(chatId).only_popular;
buttons = getButtonsByNames(config.defaulttext.buttons_settings_menu,chatId);
bot.editMessageText(config.defaulttext.menu_settings ,{
chat_id: chatId,
message_id : data.message.message_id,
parse_mode: 'HTML',
reply_markup : JSON.stringify({ inline_keyboard: buttons })
});
update_users.set(chatId);
break;
case "inline_dowload":
inline_dowload_track(data.inline_message_id,callback_data.id)
break;
default:
bot.answerCallbackQuery(callbackId,'Кнопка пока не работает'); //////need_config_text
}
});
/*
bot.on("chosen_inline_result", function(data){
console.log(data);
if(data.result_id!=0)
inline_dowload_track(data.inline_message_id,data.result_id);
});*/
async function inline_dowload_track(msgId,trackId){
if(music_ids.get(trackId)) bot.editMessageMedia({type:'document', media:music_ids.get(trackId), mime_type:"audio/mpeg",caption:""},{ inline_message_id: msgId});
else{
bot.editMessageText("Происходит загрузка с серверов Spotify..." ,{
inline_message_id: msgId
})
let spotify = new SpotifyDownloadApi(options);
let file = await spotify.downloadTrack("https://api.spotify.com/v1/tracks/"+trackId);
bot.editMessageText("Загружаем в телеграмм..." ,{
inline_message_id: msgId
})
file = await bot.sendDocument(-746476380,file);
music_ids.set(trackId,file.audio.file_id)
bot.editMessageMedia({type:'document', media:file.audio.file_id, mime_type:"audio/mpeg",caption:""},{ inline_message_id: msgId
})
}
}
bot.on("inline_query", function(data){
let is_Auth = users_keys.get(data.from.id) != undefined;
if(is_Auth) is_Auth = users_keys.get(data.from.id).refreshToken != 'unauthorized';
if(!is_Auth) {
var answers = JSON.stringify([
{type:'article',id: "0", title:"Необходима авторизация", input_message_content:{message_text:"Для авторизации перейдите в чат @MySpotifyConnectBot"}, is_personal:true}
]);
bot.answerInlineQuery(data.id,answers);
}
else search_and_answer_inline_query(data);
});
async function search_and_answer_inline_query(data){
var temp_spotifyApi = await getUserByRefreshToken(users_keys.get(data.from.id).refreshToken,options);
var find = await spotify_search(data.query,temp_spotifyApi,10);
var answers = [];
for await(var track of find.body.tracks.items) {
var artists = '';
for (const artist of track.artists)
artists += artist.name + ', ';
artists = artists.substring(0,artists.length-2);
if(music_ids.get(track.id)) answers.push({type:'document',id: track.id, title:track.name, description:artists, document_url:music_ids.get(track.id), mime_type:"audio/mpeg"});
else answers.push({type:'document',id: track.id, title:track.name, description:artists, caption:`Для загрузки ${track.name} - ${artists} нажмите кнопку`, document_url:'CQACAgIAAxkBAAIg7GGbzO7SzDUQqGzL8jNWVWorktCvAAIyEwACDEnhSMaVtC8QCrvPIgQ', mime_type:"audio/mpeg", thumb_url:track.album.images[0].url, /*input_message_content:{message_text:`Для загрузки <code>${track.name} - ${artists}</code> нажмите кнопку`},*/ reply_markup:{parse_mode:"HTML",inline_keyboard:[[{ text: 'Скачать', callback_data: JSON.stringify({command:"inline_dowload",id:track.id}) }]]}});
}
var answers = JSON.stringify(answers);
bot.answerInlineQuery(data.id,answers);
}
/******************--- SpotifyInit ----**************************/
var SpotifyWebApi = require('spotify-web-api-node');
var spotifyClientId = process.env.SPOTIFY_CLIENT_ID;
var spotifyClientSecret = process.env.SPOTIFY_CLIENT_SECRET;
var spotifyRedirectUri = process.env.SPOTIFY_REDIRECT_URI;
var options = {
clientId: spotifyClientId,
clientSecret: spotifyClientSecret,
redirectUri: spotifyRedirectUri
}
var spotifyApi = new SpotifyWebApi(options);
/******************--- SpotifyInit ----**************************/
/******************--- getAccessToken ----**************************/
async function getUserByRefreshToken(refreshToken, options){
// console.log(options);
var temp_spotifyApi = new SpotifyWebApi(options);
await temp_spotifyApi.setRefreshToken(refreshToken);
const data = await temp_spotifyApi.refreshAccessToken();
temp_spotifyApi.setAccessToken(data.body['access_token']);
return temp_spotifyApi;
}/*
async function getServerToken(options){
// console.log(options);
var temp_spotifyApi = new SpotifyWebApi(options);
const data = await temp_spotifyApi.clientCredentialsGrant();
temp_spotifyApi.setAccessToken(data.body['access_token']);
return temp_spotifyApi;
}*/
/******************--- getAccessToken ----**************************/
/******************--- databaseConnect ----**************************/
const { Client } = require('pg');
const client = new Client({
connectionString: process.env.DATABASE_URL,
ssl: {
rejectUnauthorized: false
}
})
client.connect()
.catch(e => {
console.error(e);
})
.then(function(){
(async () => {
var create_table = `CREATE TABLE IF NOT EXISTS USERS(
ID INT PRIMARY KEY NOT NULL,
REFRESH_TOKEN VARCHAR(150) NOT NULL DEFAULT 'unauthorized',
ONLY_NOT_EXPLICIT BOOLEAN NOT NULL DEFAULT FALSE,
ONLY_POPULAR BOOLEAN NOT NULL DEFAULT FALSE,
LIKED VARCHAR(25) NOT NULL DEFAULT 'nothing',
YANDEX VARCHAR(50) NOT NULL DEFAULT '{"token":"unauthorized"}'
);`;
await client.query(create_table)
var load_users = `SELECT * FROM USERS;`;
await client.query(load_users, (err,res) => {
var users = res.rows;
for(var i=0; i<users.length;i++) {
users_keys.set(users[i].id, {
refreshToken : users[i].refresh_token,
yandex: JSON.parse(users[i].yandex),
only_not_explicit : users[i].only_not_explicit,
only_popular : users[i].only_popular,
liked : users[i].liked,
is_waiting : false
});
}
})
setTimeout(getUpdateUsers, 5000);
})()
.catch(e => {
console.error(e);
});
});
/******************--- databaseConnect ----**************************/
/******************--- newUsersCheck ----**************************/
const newUsersClient = new Client({
connectionString: process.env.DATABASE_URL,
ssl: {
rejectUnauthorized: false
}
});
newUsersClient.connect();
function getUpdateUsers(){
(async () => {
var load_users = `SELECT * FROM USERS;`;
await newUsersClient.query(load_users, (err,res) => {
var users = res.rows;
for(var i=0; i<users.length;i++) {
if(!users_keys.get(users[i].id))
users_keys.set(id,{
refreshToken : 'unauthorized',
yandex : {
token: 'unauthorized'
},
only_not_explicit : false,
only_popular : false,
is_waiting : false
});
if(users_keys.get(users[i].id).refreshToken == 'unauthorized' && users[i].refresh_token != 'unauthorized'){
users_keys.get(users[i].id).refreshToken = users[i].refresh_token;
bot.sendMessage(users[i].id, "Авторизация прошла успешно. Меню можно вызвать с помощью /menu"); //////need_config_text
}
if(users_keys.get(users[i].id).yandex.token == 'unauthorized' && JSON.parse(users[i].yandex).token != 'unauthorized'){
users_keys.get(users[i].id).yandex = JSON.parse(users[i].yandex);
bot.sendMessage(users[i].id, "Авторизация в яндексе прошла успешно"); //////need_config_text
}
}
})
setTimeout(getUpdateUsers, 5000);
})()
.catch(e => {
console.error(e);
setTimeout(getUpdateUsers, 5000);
});
}
/******************--- newUsersCheck ----**************************/
var update_users = new Map();
const updateUsersClient = new Client({
connectionString: process.env.DATABASE_URL,
ssl: {
rejectUnauthorized: false
}
});
updateUsersClient.connect();
setTimeout(updateUsersOnServer, 5000);
async function updateUsersOnServer(){
update_users.forEach(async(value,key,map)=>{
map.delete(key);
let update = `UPDATE USERS SET ONLY_NOT_EXPLICIT = ${users_keys.get(key).only_not_explicit}, ONLY_POPULAR = ${users_keys.get(key).only_popular}, LIKED = '${users_keys.get(key).liked}' WHERE ID = ${key};`
await updateUsersClient.query(update)
})
setTimeout(updateUsersOnServer, 5000);
}