Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Статья о том, как Spotify Web API (SWA) и платформа Google Apps Script (GAS) позволили превратить библиотеку в гибкий конструктор плейлистов с бесплатным исполнением по расписанию.
Под конструктором плейлистов понимаем механизм сбора, фильтрации, сортировки и добавления треков.
Ссылки на исходный код и документацию в конце статьи.
Проблема
Наличие официального API породило для Spotify множество интересных инструментов. В нашем контексте рассмотрим Smarter Playlists. Графический интерфейс в виде графов, множество управляющих блоков делают его довольно дружелюбным для обычного пользователя.
Плотное использование сервиса выявило ряд недостатков: отсутствие истории прослушиваний, лимитированное добавление треков, ограниченное количество запусков по расписанию, некорректная работа с кириллицей. С течением времени сюда добавляется желание новых источников треков, более сложных алгоритмов фильтрации. Сервис перестал развиваться с точки зрения новых функций.
В связи с этим появилось желание альтернативы, устраняющей данные недостатки.
Решение
В результате была разработана библиотека для GAS на JavaScript - Goofy. Конструктором её делает возможность запуска на платформе в редакторе или по расписанию (триггерам) без стороннего ПО.
Естественно GAS накладывает свои ограничения, но другого порядка. Например, время исполнения не более 6 минут; количество запросов к внешним API не более 20 тысяч в день. С другой стороны, круг возможностей существенно расширился. Реализованы все функции Smarter Playlists, устранены его недостатки. Появились новые функции.
Алгоритм
Несколько простых примеров, которые можно реализовать с помощью Goofy
Объединение личных миксов с удалением ранее прослушанных треков
Выявление давно непрослушиваемых треков
Сбор новинок отслеживаемых исполнителей
Накопление треков обновляемого источника в плейлисте с удалением уже прослушанных
Рекомендации Last.fm любого пользователя, топ за период и прочее
Новые возможности
Особое внимание уделю истории прослушиваний. Частое прослушивание музыки без особо активных действий приводят стриминг платформы к повторам. Одни и те же треки приходят изо дня в день. Goofy позволяет удалить ранее прослушанные треки. Однако это сложнее, чем казалось на первых взгляд.
SWA дает возможность получить только 50 последних прослушанных треков. Появление 51-ого делает недоступным 1-й.
GAS имеет выход к Google Drive. Библиотека создает повторяющийся триггер и опрашивает SWA на предмет новых прослушиваний. Если они есть, сохраняет в файл. Таким образом, появляется локальная полная история прослушиваний.
Есть другая проблема. Трек считается прослушанным только после 30 секунд. Причем зачастую недавние треки обновляются не сразу или вовсе теряются. Списываю это на "качество" SWA.
Решение есть и здесь - использовать Last.fm. Реализовано два подхода. Во первых, можно просто запросить недавние прослушивания и удалять совпадения по названию трека. Во вторых, можно выполнить поиск трека в Spotify и сохранить его в файл на Google Drive. Тем самым получая историю прослушиваний от Last.fm готовую к работе со Spotify.
Кроме того, Last.fm API используется и для получения других источников. Например, рекомендации, треки соседей по музыкальным вкусам, любимые треки, топ за разный период.
Пример
Нужно выполнить установку (копирование в GAS) и настройку (выдача разрешений, ключи доступа). Все подробно есть в документации.
1) Простой пример: получить любимые треки, взять пять случайных и добавить в плейлист.
Далее графическими средствами GAS создаем триггер. В результате, например, раз в минуту плейлист будет обновляться пятью случайными треками.
function createHelloPlaylist() {
let tracks = Source.getSavedTracks();
Selector.keepRandom(tracks, 5);
Playlist.saveWithReplace({
name: 'Hello, playlist',
tracks: tracks,
});
}
2) Выявить любимые треки, которые не были прослушаны более чем месяц.
function templateSavedAndForgot(){
let recentTracks = Source.getRecentTracks(2500);
let savedTracks = Source.getSavedTracks();
Filter.removeTracks(savedTracks, recentTracks);
let startDate = new Date('2006-01-01');
let endDate = Filter.getDateRel(30, 'endDay');
Filter.rangeDateAbs(savedTracks, startDate, endDate);
Selector.keepRandom(savedTracks, 20);
Order.sort(savedTracks, 'meta.added_at', 'asc');
Playlist.saveWithReplace({
name: 'Любимо и забыто',
tracks: savedTracks,
randomCover: 'update', // установить случайную обложку плейлиста
});
}
3) Получить треки альбомов и синглов отслеживаемых исполнителей за неделю.
function createNewRelease() {
const playlistId = 'abc';
let tracks = Source.getArtistsTracks({
artist: {
followed_include: true
},
album: {
groups: 'album,single',
release_date: { sinceDays: 7, beforeDays: 0 }
},
});
Order.shuffle(tracks);
Combiner.push(tracks, Source.getPlaylistTracks('name', playlistId));
Filter.removeTracks(tracks, RecentTracks.get(3000));
Filter.matchOriginalOnly(tracks);
Playlist.saveWithReplace({
id: playlistId,
name: 'Новые релизы',
tracks: tracks,
randomCover: 'update',
});
}
Ссылки
Документация писалась с ориентиром на пользователя, который не знаком с программированием. Чтобы дать возможность использовать Goofy через копипаст шаблонов и примеров.
Исходный код на GitHub, включая форум.