Загрузил архивные файлы
This commit is contained in:
commit
e1150bc661
9
README.md
Normal file
9
README.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# MySpotifyConnect
|
||||||
|
|
||||||
|
## После ухода spotify из россии не поддерживается, хотя вроде работает еще на старых аккаунтах
|
||||||
|
|
||||||
|
Бот для работы с плейлистами Spotify. Различные фильтры для создания плейлистов.
|
||||||
|
|
||||||
|
Можно перенести песни из VK Music или Yandex Music с минимальными потерями - почти все песни найдутся на серверах Spotify!
|
||||||
|
|
||||||
|
Бот доступен в телеграмме @MySpotifyConnectBot
|
386
config-example.js
Normal file
386
config-example.js
Normal file
@ -0,0 +1,386 @@
|
|||||||
|
var config = {};
|
||||||
|
|
||||||
|
config.defaulttext = {
|
||||||
|
need_wait : `Бот уже работает, подождите окончание выполнения предыдущей команды`,
|
||||||
|
need_admin : `Команда недоступна для данного аккаунта`,
|
||||||
|
need_auth : {
|
||||||
|
answer : `Необходима авторизация`,
|
||||||
|
buttons : ['auth']
|
||||||
|
},
|
||||||
|
unknown : `Список доступных команд доступен по команде /help
|
||||||
|
Либо откройте меню по команде /menu`,
|
||||||
|
playlist_created : `Плейлист создан, добавляю в него треки...`,
|
||||||
|
playlist_done : `Плейлист успешно создан.
|
||||||
|
Плейлист можно найти по <b><a href="https://open.spotify.com/playlist/&{playlist_id}">ссылке</a></b>`,
|
||||||
|
playlist_save : `Сохранить плейлист себе`,
|
||||||
|
playlist_create : {
|
||||||
|
playlist_name : `Избранные треки`,
|
||||||
|
playlist_description : `Избранные треки пользователя &{name}. Плейлист создан с помощью @MySpotifyConnectBot`,
|
||||||
|
playlist_name_not_russian : `Избранные зарубежные треки`,
|
||||||
|
playlist_description_not_russian : `Зарубежные треки пользователя &{name}. Плейлист создан с помощью @MySpotifyConnectBot`,
|
||||||
|
playlist_name_dance : `Избранные танцевальные треки`,
|
||||||
|
playlist_description_dance : `Танцевальные треки пользователя &{name}. Плейлист создан с помощью @MySpotifyConnectBot`,
|
||||||
|
playlist_name_not_explicit : `Избранные треки без мата`,
|
||||||
|
playlist_description_not_explicit : `Нематерные треки пользователя &{name}. Плейлист создан с помощью @MySpotifyConnectBot`,
|
||||||
|
playlist_created : `Получаю данные профиля, ищу сохраненные песни...`,
|
||||||
|
process_started : `Необходимо добавить &{total} треков`,
|
||||||
|
playlist_get : `Получаю данные плейлиста...`,
|
||||||
|
//in_process : `Осталось примерно &{offset} треков из &{total}`,
|
||||||
|
in_process : `Получено &{offset} треков из &{total}`,
|
||||||
|
empty_playlist : `У вас отсуствуют треки в медиатеке`
|
||||||
|
},
|
||||||
|
playlist_vk_create : {
|
||||||
|
playlist_name : `Аудиозаписи &{first_name} &{last_name}`,
|
||||||
|
playlist_vk_get : `Получаем аудиозаписи из вк`,
|
||||||
|
vk_in_process : `Получено &{done} треков`,
|
||||||
|
vk_search_in_process : `Найдено &{done} треков из &{all} (не найдено &{errors})`,
|
||||||
|
vk_text_while_add_in_process: `Плейлист в вк создан, начинаю добавлять туда песни...`,
|
||||||
|
vk_add_in_process : `В плейлист добавлено &{done} треков`,
|
||||||
|
playlist_just_created : `Аудиозаписи из вк получены. Происходит обработка...`,
|
||||||
|
playlist_in_process : `Аудиозаписи из вк получены. Начат поиск треков в Spotify...`,
|
||||||
|
playlist_full_created : `Плейлист создан`,
|
||||||
|
playlist_created : `Плейлист создан, поиск треков...`,
|
||||||
|
playlist_description_profile : `Музыка пользователя из социальной сети vk. Плейлист создан с помощью @MySpotifyConnectBot`,
|
||||||
|
playlist_description_playlist : `Автор плейлиста: &{first_name} &{last_name} | Плейлист создан с помощью @MySpotifyConnectBot`,
|
||||||
|
in_process : `Найдено &{done} треков из &{total}, не найдено &{errors}`,
|
||||||
|
wrong_id : `Неправильный id профиля`,
|
||||||
|
wrong_profile_url : `Неправильная ссылка на профиль`,
|
||||||
|
rule : `Для использования команды необходимо прислать ссылку на профиль vk, из которого необходимо брать музыку\n
|
||||||
|
Например: /vk_to_playlist vk.com/durov
|
||||||
|
Или: /vk_to_playlist https://vk.com/durov`,
|
||||||
|
wrong_playlist_url : `Неправильная ссылка на плейлист`,
|
||||||
|
wrong_playlist_private : `Проверьте настройки приватности и ссылку на плейлист.
|
||||||
|
Музыка должна быть доступна всем, если плейлист не ваш, а настройки приватности не позволяют его видеть всем, то добавьте его в свою музыку и скопируйте ссылку на плейлист в вашей музыке`,
|
||||||
|
playlist_rule : `Для использования команды необходимо прислать ссылку на плейлист vk, из которого необходимо брать музыку\n
|
||||||
|
Например: /vk_get_playlist vk.com/music?z=audio_playlist-147845620_6
|
||||||
|
Или: /vk_get_playlist https://vk.com/audios0?&z=audio_playlist-147845620_6`
|
||||||
|
},
|
||||||
|
menu_main : `📝➖➖➖📍<b>Меню</b>📍➖➖➖📝
|
||||||
|
Выберите нужный пункт меню`,
|
||||||
|
buttons_main_menu : ['profile_menu','create_playlist','vk_menu','settings','help'],
|
||||||
|
menu_profile : `📝➖➖➖📍<b>Профиль</b>📍➖➖➖📝
|
||||||
|
Выберите нужный пункт меню`,
|
||||||
|
buttons_profile_menu : ['profile','player_menu','main_menu'],
|
||||||
|
menu_vk : `📝➖➖➖📍<b>Импорт из VK</b>📍➖➖➖📝
|
||||||
|
Выберите нужный пункт меню`,
|
||||||
|
buttons_vk_menu : ['import_vk_profile','import_vk_playlist','main_menu'],
|
||||||
|
menu_playlists : `📝➖➖➖📍<b>Создать плейлист</b>📍➖➖➖📝
|
||||||
|
Выберите какие песни будут в плейлисте`,
|
||||||
|
buttons_playlists_menu : ['create_playlist_from_liked','create_dance_playlist_from_liked','create_not_russian_playlist_from_liked','main_menu'],
|
||||||
|
menu_settings : `📝➖➖➖📍<b>Настройки</b>📍➖➖➖📝
|
||||||
|
Для переключения настроек, нажмите на нужный пункт`,
|
||||||
|
buttons_settings_menu : ['filter_explicit','filter_popular','logout','main_menu'],
|
||||||
|
menu_player : `📝➖➖➖📍<b>Сейчас играет</b>📍➖➖➖📝
|
||||||
|
|
||||||
|
🎵<b>&{track_name}</b>`,
|
||||||
|
buttons_player_menu : ['remote_control','download_track','profile_menu','player_menu'],
|
||||||
|
}
|
||||||
|
|
||||||
|
config.commands = new Map([
|
||||||
|
[`/start`, {
|
||||||
|
need_auth : false,
|
||||||
|
answer : `Вас приветствует бот для работы с аккаунтом Spotify\nЧтобы посмотреть доступные команды введите /help`,
|
||||||
|
another_after_login : true,
|
||||||
|
answer_after_login : `Рад видеть вас снова.\nЧтобы посмотреть доступные команды введите /help`,
|
||||||
|
buttons : ['auth'],
|
||||||
|
buttons_after_login : []
|
||||||
|
}],
|
||||||
|
[`/help`, {
|
||||||
|
need_auth : false,
|
||||||
|
answer : `<b>Список доступных команд:</b>`,
|
||||||
|
have_description : false,
|
||||||
|
description : `Список доступных команд`,
|
||||||
|
buttons : [],
|
||||||
|
buttons_after_login : ['main_menu'],
|
||||||
|
function_name : "help"
|
||||||
|
}],
|
||||||
|
[`/login`, {
|
||||||
|
need_auth : false,
|
||||||
|
need_admin : false,
|
||||||
|
answer :
|
||||||
|
`Для авторизации откройте <b><a href="&{url}">ссылку</a></b> и следуйте указаниям.
|
||||||
|
Нажмите на кнопку выйти для того, чтобы выйти из аккаунта Spotify в веб браузере`,
|
||||||
|
have_description : true,
|
||||||
|
description : `Авторизация`,
|
||||||
|
another_after_login : true,
|
||||||
|
answer_after_login : `Вы уже авторизованы. Если вы хотите выйти, введите /logout`,
|
||||||
|
buttons : ['auth','logout'],
|
||||||
|
buttons_after_login : ['main_menu'],
|
||||||
|
function_name : "login"
|
||||||
|
}],
|
||||||
|
[`/menu`, {
|
||||||
|
need_auth : true,
|
||||||
|
have_description : true,
|
||||||
|
description : `Меню бота`,
|
||||||
|
answer : `📝➖➖➖📍<b>Меню</b>📍➖➖➖📝
|
||||||
|
Выберите нужный пункт меню`,
|
||||||
|
buttons : ['profile_menu','create_playlist','vk_menu','settings','help']
|
||||||
|
}],
|
||||||
|
[`/info`, {
|
||||||
|
need_auth : true,
|
||||||
|
answer :
|
||||||
|
`<b>Имя пользователя:</b> &{name}
|
||||||
|
<b>Email:</b> &{email}
|
||||||
|
<b>Подписчиков:</b> &{followers}
|
||||||
|
<b>Всего треков:</b> &{total}`,
|
||||||
|
have_description : true,
|
||||||
|
description : `Информация о профиле`,
|
||||||
|
buttons : ['top_tracks','top_artists'],
|
||||||
|
function_name : "info_about_user"
|
||||||
|
}],
|
||||||
|
[`/tracks`, {
|
||||||
|
need_auth : true,
|
||||||
|
answer : `<b>💬Список избранных треков:</b>`,
|
||||||
|
have_description : false,
|
||||||
|
description : `Последние 20 добавленных треков`,
|
||||||
|
buttons : [],
|
||||||
|
function_name : "user_tracks"
|
||||||
|
}],
|
||||||
|
[`/top_tracks`, {
|
||||||
|
need_auth : true,
|
||||||
|
answer : `<b>💬Топ треков пользователя:</b>`,
|
||||||
|
have_description : true,
|
||||||
|
description : `Топ треков пользователя`,
|
||||||
|
buttons : ['top_artists'],
|
||||||
|
function_name : "top_tracks"
|
||||||
|
}],
|
||||||
|
[`/top_artists`, {
|
||||||
|
need_auth : true,
|
||||||
|
answer : `<b>💬Топ исполнителей пользователя:</b>`,
|
||||||
|
have_description : true,
|
||||||
|
description : `Топ треков исполнителей`,
|
||||||
|
buttons : ['top_tracks'],
|
||||||
|
function_name : "top_artists"
|
||||||
|
}],
|
||||||
|
[`/remote_control`, {
|
||||||
|
need_auth : true,
|
||||||
|
answer : `📝➖➖➖📍<b>Сейчас играет</b>📍➖➖➖📝
|
||||||
|
|
||||||
|
🎵 <b><code>&{track_name}</code></b>`,
|
||||||
|
have_description : false,
|
||||||
|
description : `Управление текущим воспроизведением`,
|
||||||
|
buttons : ['remote_control','download_track'],
|
||||||
|
function_name : "remote_control"
|
||||||
|
}],
|
||||||
|
[`/save_to_playlist`, {
|
||||||
|
need_auth : true,
|
||||||
|
answer : `Плейлист успешно создан.
|
||||||
|
Плейлист можно найти у себя в музыке и по <b><a href="https://open.spotify.com/playlist/&{playlist_id}">ссылке</a></b>`,
|
||||||
|
have_description : true,
|
||||||
|
description : `Создать плейлист из избранных треков`,
|
||||||
|
buttons : [],
|
||||||
|
function_name : "create_playlist_from_liked"
|
||||||
|
}],
|
||||||
|
[`/save_english_to_playlist`, {
|
||||||
|
need_auth : true,
|
||||||
|
have_description : true,
|
||||||
|
description : `Создать плейлист из избранных зарубежных треков`,
|
||||||
|
buttons : [],
|
||||||
|
function_name : "create_english_playlist_from_liked"
|
||||||
|
}],
|
||||||
|
[`/save_dance_to_playlist`, {
|
||||||
|
need_auth : true,
|
||||||
|
have_description : true,
|
||||||
|
description : `Создать плейлист из избранных танцевальных треков`,
|
||||||
|
buttons : [],
|
||||||
|
function_name : "create_dance_playlist_from_liked"
|
||||||
|
}],
|
||||||
|
/* [`/save_not_explicit_to_playlist`, {
|
||||||
|
need_auth : true,
|
||||||
|
have_description : true,
|
||||||
|
description : `Создать плейлист из избранных нематерных треков`,
|
||||||
|
buttons : [],
|
||||||
|
function_name : "create_not_explicit_playlist_from_liked"
|
||||||
|
}],*/
|
||||||
|
[`/vk_to_playlist`, {
|
||||||
|
need_auth : true,
|
||||||
|
need_admin : false,
|
||||||
|
answer : `Плейлист успешно создан.
|
||||||
|
Плейлист можно найти у себя в музыке и по <b><a href="https://open.spotify.com/playlist/&{playlist_id}">ссылке</a></b>`,
|
||||||
|
have_description : true,
|
||||||
|
description : `Создать плейлист из треков профиля вк. При вызове напишите ссылку на профиль vk через пробел от команды`,
|
||||||
|
buttons : [],
|
||||||
|
function_name : "create_playlist_from_vk"
|
||||||
|
}],
|
||||||
|
[`/vk_get_playlist`, {
|
||||||
|
need_auth : true,
|
||||||
|
need_admin : false,
|
||||||
|
answer : `Плейлист успешно создан.
|
||||||
|
Плейлист можно найти у себя в музыке и по <b><a href="https://open.spotify.com/playlist/&{playlist_id}">ссылке</a></b>`,
|
||||||
|
have_description : true,
|
||||||
|
description : `Импортировать плейлист вк. При вызове напишите ссылку на плейлист vk через пробел от команды`,
|
||||||
|
buttons : [],
|
||||||
|
function_name : "create_playlist_from_vk_playlist"
|
||||||
|
}],
|
||||||
|
[`/download`, {
|
||||||
|
need_auth : true,
|
||||||
|
need_admin : false,
|
||||||
|
have_description : true,
|
||||||
|
description : `Скачать трек по названию/исполнителю. При вызове напишите слова для поиска песни через пробел от команды`,
|
||||||
|
answer : `Трек не найден`,
|
||||||
|
buttons : [],
|
||||||
|
function_name : "download_track"
|
||||||
|
}],
|
||||||
|
[`/logout`, {
|
||||||
|
need_auth : true,
|
||||||
|
need_admin : false,
|
||||||
|
answer : `Вы успешно вышли из аккаунта`,
|
||||||
|
have_description : true,
|
||||||
|
description : `Выйти из аккаунта`,
|
||||||
|
buttons : ['auth'],
|
||||||
|
function_name : "logout"
|
||||||
|
}],
|
||||||
|
]);
|
||||||
|
|
||||||
|
config.admin_commands = new Map([
|
||||||
|
[`/yandex_login`, {
|
||||||
|
need_auth : true,
|
||||||
|
need_admin : true,
|
||||||
|
have_description : true,
|
||||||
|
description : `yandex login`,
|
||||||
|
buttons : [],
|
||||||
|
function_name : "yandex_login"
|
||||||
|
}],
|
||||||
|
[`/yandex_to_playlist`, {
|
||||||
|
need_auth : true,
|
||||||
|
need_admin : true,
|
||||||
|
have_description : true,
|
||||||
|
description : `Создать плейлист из треков профиля Yandex в Spotify`,
|
||||||
|
buttons : [],
|
||||||
|
function_name : "create_playlist_from_yandex"
|
||||||
|
}],
|
||||||
|
[`/list_of_users`, {
|
||||||
|
using_spotifyApi : true,
|
||||||
|
need_auth : false,
|
||||||
|
need_admin : true,
|
||||||
|
answer : `<b>Список пользователей(&{count}):</b>`,
|
||||||
|
have_description : true,
|
||||||
|
description : `Список пользователей`,
|
||||||
|
show_after_login : true,
|
||||||
|
buttons : [],
|
||||||
|
function_name : "show_list_of_users"
|
||||||
|
}],
|
||||||
|
[`/update_all_liked`, {
|
||||||
|
using_spotifyApi : true,
|
||||||
|
need_auth : false,
|
||||||
|
need_admin : true,
|
||||||
|
answer : `Запущен процесс...`,
|
||||||
|
have_description : true,
|
||||||
|
description : `Обновить все плейлисты с избранными треками`,
|
||||||
|
show_after_login : true,
|
||||||
|
buttons : [],
|
||||||
|
function_name : "update_all_liked"
|
||||||
|
}],
|
||||||
|
[`/test`, {
|
||||||
|
need_auth : false,
|
||||||
|
need_admin : true,
|
||||||
|
answer : `test`,
|
||||||
|
have_description : true,
|
||||||
|
description : `test`,
|
||||||
|
show_after_login : false,
|
||||||
|
buttons : []
|
||||||
|
}],
|
||||||
|
[`/query`, {
|
||||||
|
need_auth : false,
|
||||||
|
need_admin : true,
|
||||||
|
answer : `query answer\n`,
|
||||||
|
have_description : false,
|
||||||
|
buttons : [],
|
||||||
|
function_name : "query"
|
||||||
|
}],
|
||||||
|
[`/login_server`, {
|
||||||
|
need_auth : false,
|
||||||
|
need_admin : true,
|
||||||
|
answer : `Ссылки на все `,
|
||||||
|
have_description : false,
|
||||||
|
buttons : []
|
||||||
|
}],
|
||||||
|
[`/get_info`, {
|
||||||
|
need_auth : true,
|
||||||
|
need_admin : true,
|
||||||
|
answer : `get_info`,
|
||||||
|
have_description : true,
|
||||||
|
description : `get_info`,
|
||||||
|
buttons : [],
|
||||||
|
function_name : "get_info"
|
||||||
|
}],
|
||||||
|
[`/server_login`, {
|
||||||
|
need_auth : false,
|
||||||
|
need_admin : true,
|
||||||
|
answer : `<a href='&{url}'>Авторизация сервера</a>\n`,
|
||||||
|
have_description : false,
|
||||||
|
buttons : [],
|
||||||
|
function_name : "server_login"
|
||||||
|
}],
|
||||||
|
[`/spotify_to_playlist`, {
|
||||||
|
need_auth : true,
|
||||||
|
need_admin : false,
|
||||||
|
have_description : true,
|
||||||
|
description : `Создать плейлист из треков профиля Spotify в Vk`,
|
||||||
|
buttons : [],
|
||||||
|
function_name : "create_playlist_in_vk"
|
||||||
|
}],
|
||||||
|
[`/like_playlist`, {
|
||||||
|
need_auth : true,
|
||||||
|
need_admin : false,
|
||||||
|
have_description : true,
|
||||||
|
description : `Лайкнуть каждую песню плейлиста`,
|
||||||
|
buttons : [],
|
||||||
|
function_name : "like_playlist"
|
||||||
|
}],
|
||||||
|
]);
|
||||||
|
|
||||||
|
config.options = {
|
||||||
|
user_options : [
|
||||||
|
{
|
||||||
|
clientId: '',
|
||||||
|
clientSecret: '',
|
||||||
|
redirectUri: ''
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
server_options: [
|
||||||
|
{
|
||||||
|
clientId: '',
|
||||||
|
clientSecret: '',
|
||||||
|
redirectUri: '',
|
||||||
|
refreshToken: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
clientId: '',
|
||||||
|
clientSecret: '',
|
||||||
|
redirectUri: '',
|
||||||
|
refreshToken: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
clientId: '',
|
||||||
|
clientSecret: '',
|
||||||
|
redirectUri: '',
|
||||||
|
refreshToken: ''
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
config.scopes = [
|
||||||
|
`ugc-image-upload`,
|
||||||
|
`user-read-playback-state`,
|
||||||
|
`user-modify-playback-state`,
|
||||||
|
`user-read-currently-playing`,
|
||||||
|
`streaming`,
|
||||||
|
`app-remote-control`,
|
||||||
|
`user-read-email`,
|
||||||
|
`user-read-private`,
|
||||||
|
`playlist-read-collaborative`,
|
||||||
|
`playlist-modify-public`,
|
||||||
|
`playlist-read-private`,
|
||||||
|
`playlist-modify-private`,
|
||||||
|
`user-library-modify`,
|
||||||
|
`user-library-read`,
|
||||||
|
`user-top-read`,
|
||||||
|
`user-read-playback-position`,
|
||||||
|
`user-read-recently-played`,
|
||||||
|
`user-follow-read`,
|
||||||
|
`user-follow-modify`
|
||||||
|
];
|
||||||
|
|
||||||
|
module.exports = config;
|
33
package.json
Normal file
33
package.json
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"name": "MySpotifyTransfer",
|
||||||
|
"version": "0.3.26062021",
|
||||||
|
"description": "A sample spotify transfer",
|
||||||
|
"engines": {
|
||||||
|
"node": "12.x"
|
||||||
|
},
|
||||||
|
"main": "starter.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node starter.js",
|
||||||
|
"test": "node test.js"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"easyvk": "^2.8.2",
|
||||||
|
"ejs": "^2.5.6",
|
||||||
|
"express": "^4.15.2",
|
||||||
|
"got": "^11.8.3",
|
||||||
|
"heroku-self-ping": "^2.0.1",
|
||||||
|
"https": "^1.0.0",
|
||||||
|
"node-telegram-bot-api": "^0.51.0",
|
||||||
|
"pastebin-ts": "^1.2.0",
|
||||||
|
"pg": "^8.5.1",
|
||||||
|
"readline": "^1.3.0",
|
||||||
|
"request": "^2.88.2",
|
||||||
|
"spotify-web-api-node": "^5.0.0",
|
||||||
|
"spotifydl-core": "^0.2.0",
|
||||||
|
"superagent": "^6.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"tape": "^4.7.0"
|
||||||
|
},
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
163
public/auth_completed.css
Normal file
163
public/auth_completed.css
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
.u-section-1 {
|
||||||
|
background-image: url("images/background.jpg");
|
||||||
|
background-position: 50% 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-section-1 .u-sheet-1 {
|
||||||
|
min-height: 711px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-section-1 .u-slider-1 {
|
||||||
|
width: 533px;
|
||||||
|
min-height: 394px;
|
||||||
|
margin: 60px auto 60px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-section-1 .u-carousel-indicators-1 {
|
||||||
|
position: absolute;
|
||||||
|
width: 32px;
|
||||||
|
height: 10px;
|
||||||
|
top: auto;
|
||||||
|
left: 0;
|
||||||
|
right: auto;
|
||||||
|
bottom: -21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-section-1 .u-carousel-item-1 {
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-section-1 .u-container-layout-1 {
|
||||||
|
padding: 30px 65px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-section-1 .u-text-1 {
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: 700;
|
||||||
|
font-family: "PT Sans", sans-serif;
|
||||||
|
font-size: 3rem;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-section-1 .u-text-2 {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
text-transform: none;
|
||||||
|
letter-spacing: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
margin: 20px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-section-1 .u-btn-1 {
|
||||||
|
background-image: none;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 3px;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
border-style: solid;
|
||||||
|
font-weight: 700;
|
||||||
|
margin: 20px auto 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-section-1 .u-carousel-control-1 {
|
||||||
|
width: 45px;
|
||||||
|
height: 45px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-section-1 .u-carousel-control-2 {
|
||||||
|
width: 45px;
|
||||||
|
height: 45px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1199px) {
|
||||||
|
.u-section-1 .u-sheet-1 {
|
||||||
|
min-height: 586px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-section-1 .u-slider-1 {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 991px) {
|
||||||
|
.u-section-1 .u-sheet-1 {
|
||||||
|
min-height: 489px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-section-1 .u-container-layout-1 {
|
||||||
|
padding-left: 30px;
|
||||||
|
padding-right: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-section-1 .u-text-1 {
|
||||||
|
width: auto;
|
||||||
|
margin-top: 44px;
|
||||||
|
margin-left: 39px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-section-1 .u-text-2 {
|
||||||
|
width: auto;
|
||||||
|
margin-right: 27px;
|
||||||
|
margin-left: 39px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-section-1 .u-btn-1 {
|
||||||
|
margin-left: 39px;
|
||||||
|
padding: 10px 31px 11px 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
.u-section-1 .u-sheet-1 {
|
||||||
|
min-height: 367px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-section-1 .u-slider-1 {
|
||||||
|
margin-right: initial;
|
||||||
|
margin-left: initial;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-section-1 .u-container-layout-1 {
|
||||||
|
padding-left: 40px;
|
||||||
|
padding-right: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-section-1 .u-text-1 {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-section-1 .u-text-2 {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-section-1 .u-btn-1 {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 575px) {
|
||||||
|
.u-section-1 .u-sheet-1 {
|
||||||
|
min-height: 800px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-section-1 .u-slider-1 {
|
||||||
|
margin-top: 80px;
|
||||||
|
width: auto;
|
||||||
|
margin-right: initial;
|
||||||
|
margin-left: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-section-1 .u-container-layout-1 {
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-section-1 .u-text-1 {
|
||||||
|
font-size: 2.625rem;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-section-1 .u-text-2 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
}
|
BIN
public/images/background.jpg
Normal file
BIN
public/images/background.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 65 KiB |
BIN
public/images/login.png
Normal file
BIN
public/images/login.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 134 KiB |
31415
public/nicepage.css
Normal file
31415
public/nicepage.css
Normal file
File diff suppressed because it is too large
Load Diff
2
starter.js
Normal file
2
starter.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
require('./bot');
|
||||||
|
require('./web');
|
78
views/pages/auth_completed.ejs
Normal file
78
views/pages/auth_completed.ejs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html style="font-size: 16px;">
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Auth completed</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="nicepage.css" media="screen">
|
||||||
|
<link rel="stylesheet" href="auth_completed.css" media="screen">
|
||||||
|
|
||||||
|
<link id="u-theme-google-font" rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,100i,300,300i,400,400i,500,500i,700,700i,900,900i|Open+Sans:300,300i,400,400i,600,600i,700,700i,800,800i">
|
||||||
|
<link id="u-page-google-font" rel="stylesheet" href="https://fonts.googleapis.com/css?family=PT+Sans:400,400i,700,700i">
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body class="u-body">
|
||||||
|
<section class="u-clearfix u-image u-section-1" id="carousel_9645">
|
||||||
|
<div class="u-clearfix u-sheet u-valign-middle u-sheet-1">
|
||||||
|
<div id="carousel-ee08" data-interval="5000" data-u-ride="carousel" class="u-carousel u-slider u-slider-1">
|
||||||
|
|
||||||
|
<div class="u-carousel-inner" role="listbox">
|
||||||
|
<div class="editor-preview-animation u-active u-carousel-item u-container-style u-slide u-white u-carousel-item-1">
|
||||||
|
<div class="u-container-layout u-valign-middle u-container-layout-1">
|
||||||
|
<h1 class="u-color-scheme-u10 u-color-style-multicolor-1 u-custom-font u-font-pt-sans u-text u-text-palette-1-dark-2 u-title u-text-1">Успешная авторизация</h1>
|
||||||
|
<p class="u-large-text u-text u-text-variant u-text-2"> Для продолжения работы перейдите обратно в Telegram</p>
|
||||||
|
<a href="https://t.me/MySpotifyConnectBot" class="u-active-white u-border-2 u-border-white u-btn u-btn-rectangle u-button-style u-hover-white u-palette-2-base u-btn-1">Перейти</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a class="u-absolute-vcenter u-carousel-control u-carousel-control-prev u-spacing-10 u-text-body-alt-color u-carousel-control-1" href="#carousel-ee08" role="button" data-u-slide="prev">
|
||||||
|
<span aria-hidden="true">
|
||||||
|
<svg viewBox="0 0 492 492"><path d="M464.344,207.418l0.768,0.168H135.888l103.496-103.724c5.068-5.064,7.848-11.924,7.848-19.124
|
||||||
|
c0-7.2-2.78-14.012-7.848-19.088L223.28,49.538c-5.064-5.064-11.812-7.864-19.008-7.864c-7.2,0-13.952,2.78-19.016,7.844
|
||||||
|
L7.844,226.914C2.76,231.998-0.02,238.77,0,245.974c-0.02,7.244,2.76,14.02,7.844,19.096l177.412,177.412
|
||||||
|
c5.064,5.06,11.812,7.844,19.016,7.844c7.196,0,13.944-2.788,19.008-7.844l16.104-16.112c5.068-5.056,7.848-11.808,7.848-19.008
|
||||||
|
c0-7.196-2.78-13.592-7.848-18.652L134.72,284.406h329.992c14.828,0,27.288-12.78,27.288-27.6v-22.788
|
||||||
|
C492,219.198,479.172,207.418,464.344,207.418z"></path></svg>
|
||||||
|
</span>
|
||||||
|
<span class="sr-only">
|
||||||
|
<svg viewBox="0 0 492 492"><path d="M464.344,207.418l0.768,0.168H135.888l103.496-103.724c5.068-5.064,7.848-11.924,7.848-19.124
|
||||||
|
c0-7.2-2.78-14.012-7.848-19.088L223.28,49.538c-5.064-5.064-11.812-7.864-19.008-7.864c-7.2,0-13.952,2.78-19.016,7.844
|
||||||
|
L7.844,226.914C2.76,231.998-0.02,238.77,0,245.974c-0.02,7.244,2.76,14.02,7.844,19.096l177.412,177.412
|
||||||
|
c5.064,5.06,11.812,7.844,19.016,7.844c7.196,0,13.944-2.788,19.008-7.844l16.104-16.112c5.068-5.056,7.848-11.808,7.848-19.008
|
||||||
|
c0-7.196-2.78-13.592-7.848-18.652L134.72,284.406h329.992c14.828,0,27.288-12.78,27.288-27.6v-22.788
|
||||||
|
C492,219.198,479.172,207.418,464.344,207.418z"></path></svg>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
<a class="u-absolute-vcenter u-carousel-control u-carousel-control-next u-spacing-10 u-text-body-alt-color u-carousel-control-2" href="#carousel-ee08" role="button" data-u-slide="next">
|
||||||
|
<span aria-hidden="true">
|
||||||
|
<svg viewBox="0 0 492.004 492.004"><path d="M484.14,226.886L306.46,49.202c-5.072-5.072-11.832-7.856-19.04-7.856c-7.216,0-13.972,2.788-19.044,7.856l-16.132,16.136
|
||||||
|
c-5.068,5.064-7.86,11.828-7.86,19.04c0,7.208,2.792,14.2,7.86,19.264L355.9,207.526H26.58C11.732,207.526,0,219.15,0,234.002
|
||||||
|
v22.812c0,14.852,11.732,27.648,26.58,27.648h330.496L252.248,388.926c-5.068,5.072-7.86,11.652-7.86,18.864
|
||||||
|
c0,7.204,2.792,13.88,7.86,18.948l16.132,16.084c5.072,5.072,11.828,7.836,19.044,7.836c7.208,0,13.968-2.8,19.04-7.872
|
||||||
|
l177.68-177.68c5.084-5.088,7.88-11.88,7.86-19.1C492.02,238.762,489.228,231.966,484.14,226.886z"></path></svg>
|
||||||
|
</span>
|
||||||
|
<span class="sr-only">
|
||||||
|
<svg viewBox="0 0 492.004 492.004"><path d="M484.14,226.886L306.46,49.202c-5.072-5.072-11.832-7.856-19.04-7.856c-7.216,0-13.972,2.788-19.044,7.856l-16.132,16.136
|
||||||
|
c-5.068,5.064-7.86,11.828-7.86,19.04c0,7.208,2.792,14.2,7.86,19.264L355.9,207.526H26.58C11.732,207.526,0,219.15,0,234.002
|
||||||
|
v22.812c0,14.852,11.732,27.648,26.58,27.648h330.496L252.248,388.926c-5.068,5.072-7.86,11.652-7.86,18.864
|
||||||
|
c0,7.204,2.792,13.88,7.86,18.948l16.132,16.084c5.072,5.072,11.828,7.836,19.044,7.836c7.208,0,13.968-2.8,19.04-7.872
|
||||||
|
l177.68-177.68c5.084-5.088,7.88-11.88,7.86-19.1C492.02,238.762,489.228,231.966,484.14,226.886z"></path></svg>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
<footer class="u-clearfix u-footer u-grey-80" id="sec-a135"><div class="u-clearfix u-sheet u-sheet-1">
|
||||||
|
<div class="u-align-center u-container-style u-group u-group-1">
|
||||||
|
<div class="u-container-layout u-valign-middle u-container-layout-1">
|
||||||
|
<p class="u-small-text u-text u-text-variant u-text-1">Made by FutureX</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
20
views/pages/index.ejs
Normal file
20
views/pages/index.ejs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1><%=title %> в EJS</h1>
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a href="https://myspotifytransfer.herokuapp.com/login" target="_self">
|
||||||
|
Login
|
||||||
|
</a></h2>
|
||||||
|
|
||||||
|
<% if(wehaveinfo) {%>
|
||||||
|
|
||||||
|
<h2><a href="https://myspotifytransfer.herokuapp.com/info" target="_self">
|
||||||
|
Info
|
||||||
|
</a></h2>
|
||||||
|
<%} %>
|
||||||
|
</body>
|
||||||
|
</html>
|
31
views/pages/info.ejs
Normal file
31
views/pages/info.ejs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1>Инфо о пользователе</h1>
|
||||||
|
|
||||||
|
<% if(display_name) {%><h3>Имя: <%=display_name %></h3><%} %>
|
||||||
|
<% if(email) {%><h3>Email: <%=email %></h3><%} %>
|
||||||
|
<% if(followers) {%><h3>Количество подписчиков: <%=followers %></h3><%} %>
|
||||||
|
|
||||||
|
<% if(tracks) {%>
|
||||||
|
<h2>Избранные треки (всего <%=total %>)</h2>
|
||||||
|
<ul>
|
||||||
|
<% for(var i=0; i<tracks.length;i++) {%>
|
||||||
|
<li>
|
||||||
|
<%=tracks[i].track.name %> -
|
||||||
|
<%=tracks[i].track.artists[0].name %>
|
||||||
|
<% for(var j=1; j<tracks[i].track.artists.length;j++) {%>
|
||||||
|
, <%=tracks[i].track.artists[j].name %>
|
||||||
|
<%} %>
|
||||||
|
</li>
|
||||||
|
<%} %>
|
||||||
|
</ul>
|
||||||
|
<%} %>
|
||||||
|
|
||||||
|
<h5><a href="https://myspotifytransfer.herokuapp.com/home" target="_self">Назад</a></h5>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
151
web.js
Normal file
151
web.js
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
const path = require('path');
|
||||||
|
//const ping = require('heroku-self-ping').default(`${process.env.HEROKU_URL}/ping`);
|
||||||
|
const express = require('express');
|
||||||
|
const packageInfo = require('./package.json');
|
||||||
|
|
||||||
|
var app = express();
|
||||||
|
app.use(express.static(path.join(__dirname, 'public')));
|
||||||
|
app.set('view engine', 'ejs');
|
||||||
|
|
||||||
|
var server = app.listen(process.env.PORT, function () {
|
||||||
|
console.log(`Обработка страниц в браузере запущена. Порт ${process.env.PORT}`);
|
||||||
|
setTimeout(ping, 1000);
|
||||||
|
});
|
||||||
|
|
||||||
|
app.get('/', function (req, res) {
|
||||||
|
res.json({ version: packageInfo.version });
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************--- saveNewUsers ----**************************/
|
||||||
|
const { Client } = require('pg');
|
||||||
|
const client = new Client({
|
||||||
|
connectionString: process.env.DATABASE_URL,
|
||||||
|
ssl: {
|
||||||
|
rejectUnauthorized: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
client.connect();
|
||||||
|
|
||||||
|
var queue = new Map();
|
||||||
|
saveNewUsers();
|
||||||
|
|
||||||
|
function saveNewUsers(){
|
||||||
|
(async () => {
|
||||||
|
var user = queue.entries().next().value;
|
||||||
|
while (user){
|
||||||
|
var add_user = `INSERT INTO USERS(ID, REFRESH_TOKEN) VALUES(${user[0]}, '${user[1]}') ON CONFLICT (ID) DO UPDATE SET REFRESH_TOKEN = EXCLUDED.REFRESH_TOKEN;`;
|
||||||
|
await client.query(add_user);
|
||||||
|
queue.delete(user[0]);
|
||||||
|
user = queue.entries().next().value;
|
||||||
|
}
|
||||||
|
setTimeout(saveNewUsers, 1000);
|
||||||
|
})()
|
||||||
|
.catch(e => {
|
||||||
|
console.error(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/******************--- saveNewUsers ----**************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************--- callback ----**************************/
|
||||||
|
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;
|
||||||
|
|
||||||
|
app.get('/callback', (req, res) => {
|
||||||
|
const error = req.query.error;
|
||||||
|
const code = req.query.code;
|
||||||
|
const state = req.query.state;
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error('Ошибка на странице авторизации:', error);
|
||||||
|
res.send(`Ошибка авторизации`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var temp_spotifyApi = new SpotifyWebApi({
|
||||||
|
clientId: spotifyClientId,
|
||||||
|
clientSecret: spotifyClientSecret,
|
||||||
|
redirectUri: spotifyRedirectUri
|
||||||
|
});
|
||||||
|
var id = parseInt(state);
|
||||||
|
|
||||||
|
temp_spotifyApi
|
||||||
|
.authorizationCodeGrant(code)
|
||||||
|
.then(data => {
|
||||||
|
const refresh_token = data.body['refresh_token'];
|
||||||
|
queue.set(id,refresh_token);
|
||||||
|
console.log(`Прошла авторизация пользователя (id = ${id}, refreshToken = '${refresh_token}')`);
|
||||||
|
res.redirect('/auth_completed');
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error getting Tokens:', error);
|
||||||
|
res.send(`Ошибка авторизации: ${error}`);
|
||||||
|
})
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
app.get('/callback_admin', (req, res) => {
|
||||||
|
const error = req.query.error;
|
||||||
|
const code = req.query.code;
|
||||||
|
const state = req.query.state;
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error('Ошибка на странице авторизации:', error);
|
||||||
|
res.send(`Ошибка авторизации`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var options = JSON.parse(decodeURI(state));
|
||||||
|
var temp_spotifyApi = new SpotifyWebApi(options);
|
||||||
|
|
||||||
|
|
||||||
|
temp_spotifyApi
|
||||||
|
.authorizationCodeGrant(code)
|
||||||
|
.then(data => {
|
||||||
|
const refresh_token = data.body['refresh_token'];
|
||||||
|
console.log(`Прошла авторизация пользователя (refreshToken = '${refresh_token}')`);
|
||||||
|
res.send(refresh_token);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error getting Tokens:', error);
|
||||||
|
res.send(`Ошибка авторизации: ${error}`);
|
||||||
|
})
|
||||||
|
|
||||||
|
});
|
||||||
|
/******************--- callback ----**************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************--- auth_completed ----**************************/
|
||||||
|
app.get('/auth_completed', (req, res) => {
|
||||||
|
res.render('pages/auth_completed');
|
||||||
|
});
|
||||||
|
/******************--- auth_completed ----**************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************--- Pinging ----**************************/
|
||||||
|
app.get('/ping', function(req, res, next) {
|
||||||
|
res.status(200).send("pong");
|
||||||
|
});
|
||||||
|
|
||||||
|
const https = require('https')
|
||||||
|
const options = {
|
||||||
|
hostname: 'myspotifytransfer.herokuapp.com',
|
||||||
|
path: '/ping',
|
||||||
|
method: 'GET'
|
||||||
|
}
|
||||||
|
function ping(){
|
||||||
|
const req = https.request(options, res => {
|
||||||
|
console.log(`Server ping - statusCode: ${res.statusCode}`)
|
||||||
|
}).end()
|
||||||
|
setTimeout(ping, 1200000);
|
||||||
|
}
|
||||||
|
/******************--- Pinging ----**************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Reference in New Issue
Block a user