Статья о том, как 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 через копипаст шаблонов и примеров.