Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Spotify Playlist Creator

Um MVP local que transforma uma lista de músicas em texto simples (uma música por linha, por exemplo Artista - Título) em uma playlist no Spotify. Ele procura no catálogo do Spotify, pontua cada resultado em relação ao que você digitou e, então, seleciona automaticamente a melhor correspondência ou a marca para revisão.

Pré-requisitos

  • Node.js >= 20
  • Para o Spotify (padrão): uma conta do Spotify e um Client ID de aplicativo do Spotify do Spotify Developer Dashboard. Nenhum client secret é necessário — a autenticação usa o fluxo de Código de Autorização com PKCE.
  • Para o YouTube (opcional): um projeto no Google Cloud Console com a YouTube Data API v3 habilitada e um OAuth 2.0 Client ID do tipo confidential. O suporte ao YouTube só é ativado quando GOOGLE_CLIENT_ID e GOOGLE_CLIENT_SECRET estão definidos; caso contrário, o app roda apenas com Spotify.

Configuração

  1. Instale as dependências:

    npm install
  2. Copie o arquivo de exemplo de configuração e preencha seu Client ID:

    cp .env.example .env

    A URI de redirecionamento deve corresponder exatamente à que você cadastrou no Dashboard:

    http://127.0.0.1:3000/auth/callback
    
  3. Inicie o servidor de API e a interface web:

    npm run dev

    A API ouve em http://127.0.0.1:3000 e a interface web em http://127.0.0.1:5173. Abra a interface, clique em Login, conclua a tela de consentimento do Spotify e volte ao app.

Habilitando o YouTube (opcional)

O YouTube/Google é um segundo provedor, à frente de um dropdown de Platform na interface. É ativado somente quando as credenciais do Google estão presentes:

  1. No Google Cloud Console, crie (ou selecione) um projeto.

  2. Em APIs & Services → Library, ative a YouTube Data API v3 (necessária para a busca/criação de playlist).

  3. Em APIs & Services → OAuth consent screen, configure o app: escolha External (ou Internal para conta de trabalho/educação), preencha os dados e, enquanto estiver em Testing, adicione seu e-mail como tester — senão a autorização do Google é recusada.

  4. Em APIs & Services → Credentials → Create credentials → OAuth client ID, crie uma credencial do tipo Web application e registre:

    • Authorized JavaScript origins — a origem da interface web:

      • desenvolvimento: http://127.0.0.1:5173
      • produção: a origem onde a SPA é servida (ex.: http://127.0.0.1:3000)
    • Authorized redirect URIs — a URI que o servidor usa:

      http://127.0.0.1:3000/api/auth/youtube/callback
      

    A redirect URI cadastrada deve casar exatamente com a que o servidor envia. Se você sobrescrever GOOGLE_REDIRECT_URI (ou rodar em outra porta/host), cadastre essa mesma URI aqui, ou o Google recusa o callback.

  5. No arquivo baixado, copie client_id e client_secret para o .env (o project_id/client_email não são usados):

    GOOGLE_CLIENT_ID=
    GOOGLE_CLIENT_SECRET=
  6. Reinicie o app. A aba YouTube passa a mostrar o botão Connect YouTube; conclua o consentimento do Google e volte.

Quando GOOGLE_CLIENT_ID e GOOGLE_CLIENT_SECRET não estão definidos, o card do YouTube exibe "Not configured on this server" e o app continua funcionando com Spotify. Quando apenas GOOGLE_CLIENT_ID está presente (sem o secret), o servidor emite um aviso e o suporte ao YouTube fica indisponível.

Problemas comuns

Erro "Este aplicativo não foi publicado" / não consegue autorizar. Isso é esperado enquanto a OAuth consent screen está no estado Testing. Duas formas de resolver:

  • Ficar no estado Testing (recomendado para uso local). Em APIs & Services → OAuth consent screen → Audience, clique em Add test users e adicione exatamente o e-mail da conta com a qual você faz login no Google, aguarde ~1-2 min para propagar e tente de novo. Em Testing o app expira em 30 dias e a data é renovada a cada edição da tela.
  • Publicar o app. Clique em Publish app no canto superior direito da mesma tela. Para a YouTube Data API v3 o Google também pode exigir verificação do app (um formulário que pode levar dias); caso isso bloqueie, prefira ficar no estado Testing com test users.

A Authorized JavaScript origin cadastrada deve casar exatamente com a origem de onde a página faz o login: http://127.0.0.1:5173 no desenvolvimento (Vite) ou http://127.0.0.1:3000 na produção. Uma origem diferente faz o Google recusar o callback.

Variáveis de ambiente

Todas são opcionais, exceto SPOTIFY_CLIENT_ID, que é obrigatória para autenticar.

Variável Padrão Descrição
SPOTIFY_CLIENT_ID — O Client ID do seu aplicativo do Spotify.
SPOTIFY_REDIRECT_URI http://127.0.0.1:3000/auth/callback Deve corresponder a uma URI de redirecionamento do Dashboard.
PORT 3000 Porta do servidor de API.
WEB_PORT 5173 Porta do servidor de desenvolvimento Vite.
WEB_BASE_URL http://127.0.0.1:${WEB_PORT} URL para a qual a API redireciona após a autenticação.
TOKEN_FILE spotify-token.json Onde o token de autenticação é persistido.
GOOGLE_CLIENT_ID (opcional) Client ID do Google OAuth 2.0. Habilita o YouTube.
GOOGLE_CLIENT_SECRET (opcional) Secret do Google OAuth 2.0. Necessário com o ID.
GOOGLE_REDIRECT_URI http://127.0.0.1:3000/api/auth/youtube/callback URI de redirect registrada no Google Cloud.
YOUTUBE_TOKEN_FILE youtube-token.json Onde o token do YouTube/Google é persistido.

Scripts

Comando Descrição
npm run dev Executa o servidor de API e a interface web juntos.
npm run dev:server Executa apenas o servidor de API (modo de observação).
npm run dev:web Executa apenas o servidor de desenvolvimento Vite.
npm run build Compila o servidor (dist-server) e a web (dist-web).
npm run start Executa o servidor compilado, que serve o build da web.
npm run typecheck Verifica os tipos do projeto inteiro.
npm test Executa a suíte do Vitest uma vez.
npm run test:watch Executa o Vitest em modo de observação.

Arquitetura

O código é dividido de modo que a lógica de domínio fique independente de framework e testável:

HTTP/API   →  PlaylistService   →  PlaylistOrchestrator   →  SpotifyService   →  SpotifyClient
   (Express)      (caso de uso)        (pipeline de busca)     (chamadas à Web API)  (fetch + token)
  • server/spotify — a borda do Spotify.
    • spotifyClient executa as chamadas fetch reais e renova o token.
    • spotifyService encapsula o contrato da Web API (busca com limite de 10 itens, criação de playlist, adição de itens em blocos de 100) e normaliza as respostas.
    • spotifyAuth implementa o fluxo OAuth 2.0 com PKCE; tokenManager faz o cache e renova o token em disco.
  • server/services — o domínio.
    • parser divide o texto de entrada em ParsedTrackLines e monta uma query de busca.
    • matcher pontua uma linha analisada em relação a uma música candidata e escolhe a melhor.
    • dedup remove músicas duplicadas por URI.
    • orchestrator executa as buscas com um limite de concorrencia, escolhe a melhor correspondência por linha e descarta duplicatas.
    • playlistService é o caso de uso que une analisar → buscar → pontuar → deduplicar → criar/adicionar.
  • server/routes — roteadores Express finos sobre o serviço, protegidos por uma verificação de token.
  • web — um pequeno SPA React + Vite que conversa com a API.

Correspondência

Cada linha analisada é pontuada contra cada música candidata usando correspondência componentizada ponderada:

Componente Peso
Artista 0,35
Título 0,45
Query completa 0,20

As pontuações se consolidam em vereditos:

Veredito Faixa de pontuação
excellent 90–100
good 80–89
review 60–79
reject abaixo de 60

Por padrão, uma correspondência é selecionada automaticamente quando sua pontuação é igual ou superior a autoThreshold (padrão 90). Qualquer valor inferior é retornado para revisão, em vez de ser adicionado automaticamente. O orquestrador ignora linhas cuja melhor correspondência não atinja a faixa de revisão (60) e conta linhas duplicadas, de modo que cada música seja adicionada apenas uma vez.

Observações sobre a API do Spotify (2026)

  • POST /playlists/{id}/items aceita no máximo 100 itens por requisição; o serviço faz a divisão em blocos (chunking) para adições maiores.
  • Os resultados de busca são limitados a 10 itens.
  • O campo popularity foi removido da API; ele é mantido opcional para que respostas em cache continuem sendo interpretadas.
  • O campo tracks de uma playlist pode aparecer como items, dependendo da versão da API.

Testes

A suíte do Vitest fica em test/ e cobre o parser, as utilidades de texto, a pontuação/correspondência, a deduplicação e o serviço de playlist de ponta a ponta, com um SpotifyService falso (sem chamadas de rede).

npm test

Sobre este projeto

Este projeto foi um exercício de uso de IA local. Ele foi concebido, implementado e depurado inteiramente a partir do opencode (CLI interativa de engenharia de software) acoplado a um modelo do Ollama: qwen3.8:27b-mlx com janela de contexto de 32k (modelo exato ollama/qwen3.8:27b-mlx-32k). Nada foi enviado a um provedor da nuvem — toda a inferência roda na máquina local.

About

Tool used to create playlist in the Spotify from text list.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages