{"id":19353562,"url":"https://github.com/elldritch/hipsterfy","last_synced_at":"2025-04-23T07:31:29.658Z","repository":{"id":56422650,"uuid":"266952876","full_name":"elldritch/hipsterfy","owner":"elldritch","description":"Find out which Spotify hipsters you and your friends both like.","archived":false,"fork":false,"pushed_at":"2023-09-22T04:26:38.000Z","size":267,"stargazers_count":7,"open_issues_count":8,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-02T10:11:55.659Z","etag":null,"topics":["music","spotify"],"latest_commit_sha":null,"homepage":"https://hipsterfy.com","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/elldritch.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-05-26T05:31:09.000Z","updated_at":"2023-09-22T02:50:34.000Z","dependencies_parsed_at":"2022-08-15T18:20:52.547Z","dependency_job_id":null,"html_url":"https://github.com/elldritch/hipsterfy","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elldritch%2Fhipsterfy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elldritch%2Fhipsterfy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elldritch%2Fhipsterfy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elldritch%2Fhipsterfy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/elldritch","download_url":"https://codeload.github.com/elldritch/hipsterfy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250391281,"owners_count":21422870,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["music","spotify"],"created_at":"2024-11-10T04:43:17.002Z","updated_at":"2025-04-23T07:31:29.131Z","avatar_url":"https://github.com/elldritch.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Hipsterfy\n\nFind out which Spotify hipsters you and your friends both like.\n\n## Usage\n\n1. Authorize Hipsterfy to access your Spotify account.\n2. Hipsterfy generates a \"friend code\" for you.\n3. Share your \"friend code\" with your friends.\n4. When submitting a friend code, Hipsterfy shows the artists you both follow, ordered by least-popular-first.\n\nYour followed artists are a combination of artists you've followed, artists of tracks you've saved, and artists of albums you've saved.\n\n## Implementation\n\n1. Get user's followed artists: https://developer.spotify.com/documentation/web-api/reference/follow/get-followed/\n2. Get user's saved tracks: https://developer.spotify.com/documentation/web-api/reference/library/get-users-saved-tracks/\n3. Get user's saved albums: https://developer.spotify.com/documentation/web-api/reference/library/get-users-saved-albums/\n4. Get anonymous Spotify bearer token: https://open.spotify.com/get_access_token?reason=transport\u0026productType=web_player\n5. Get Spotify artist insights (this undocumented API is how monthly listeners are retrieved - otherwise, we'd need to crawl) for each artist: `curl 'https://spclient.wg.spotify.com/open-backend-2/v1/artists/{artist_id}' -H 'authorization: Bearer XXXX`\n\n## Development\n\n### Running on raw metal\n\n#### Build and run the database\n\nHipsterfy provides a Dockerfile for the database image for convenience. You may also choose to run your own Postgres instance. The schema migrations are in [`./db`](./db).\n\nTo create the database container using the Docker image:\n\n```bash\n# Build the database.\nsudo docker build -f ./images/hipsterfy-db/Dockerfile -t hipsterfy-db .\n\n# Start the database initially.\n# Make sure to set environment variables correctly; these\n# are used to initialize the database on first run.\nsudo docker run --name hipsterfy-db \\\n  -p 5432:5432 \\\n  -e POSTGRES_USER=hipsterfy \\\n  -e POSTGRES_PASSWORD=hunter2 \\\n  hipsterfy-db\n```\n\nAfter the database container has been created, you can start it with:\n\n```bash\nsudo docker start hipsterfy-db\n```\n\n#### Run the job queue server\n\nHipsterfy uses [Faktory](https://github.com/contribsys/faktory) as a job queue server.\n\nTo create the job queue container:\n\n```bash\nsudo docker run --name hipsterfy-jobqueue \\\n  -p 7419:7419 \\\n  -p 7420:7420 \\\n  -e FAKTORY_PASSWORD=hunter2 \\\n  contribsys/faktory:1.4.0\n```\n\nAfter the job queue container has been created, you can start it with:\n\n```bash\nsudo docker start hipsterfy-jobqueue\n```\n\n#### Run the tracing backend\n\nHipsterfy publishes traces to any [Zipkin](https://zipkin.io/)-compatible tracing backend.\n\nAs an example, here's how to run the [Jaeger](https://www.jaegertracing.io/docs/1.18/getting-started/#migrating-from-zipkin) backend:\n\n```bash\nsudo docker run --name hipsterfy-jaeger \\\n  -p 9411:9411 \\\n  -p 16686:16686 \\\n  -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 \\\n  jaegertracing/all-in-one:1.18\n```\n\n#### Build and run the web server\n\nMake sure to populate the flags with your own:\n\n- Server port.\n- Spotify app client ID, secret, and redirect URI. (Make sure your configured redirect URI is the same as the redirect URI in Spotify, including protocol and port! Otherwise, Spotify will refuse to redirect authorizing users, or will redirect incorrectly.)\n- Postgres database connection string.\n- Faktory host, port, and password.\n- Tracing backend host and port.\n\n```bash\ncabal run hipsterfy -- \\\n  --port 8000 \\\n  --db 'postgresql://hipsterfy:hunter2@localhost:5432' \\\n  --spotify_client_id XXXX \\\n  --spotify_client_secret XXXX \\\n  --spotify_redirect_uri http://localhost:8000/authorize/callback \\\n  --faktory_host localhost \\\n  --faktory_port 7419 \\\n  --faktory_password hunter2\n  --zipkin_host localhost\n  --zipkin_port 9411\n```\n\n#### Build and run the worker\n\nMake sure to populate the flags with your own:\n\n- Spotify app client ID and secret.\n- Postgres database connection string.\n- Faktory host, port, and password.\n\n```bash\ncabal run hipsterfy-worker -- \\\n  --db 'postgresql://hipsterfy:hunter2@localhost:5432' \\\n  --spotify_client_id XXXX \\\n  --spotify_client_secret XXXX \\\n  --faktory_host localhost \\\n  --faktory_port 7419 \\\n  --faktory_password hunter2\n```\n\n### Running with `docker-compose`\n\n#### Starting the containers\n\nDocker Compose will start all containers for you. Make sure to set environment variables for configuration.\n\n```bash\nexport HIPSTERFY_ADDR_PORT=8000\nexport HIPSTERFY_SPOTIFY_CLIENT_ID=XXXX\nexport HIPSTERFY_SPOTIFY_CLIENT_SECRET=XXXX\nexport HIPSTERFY_SPOTIFY_REDIRECT_URI=http://localhost:8000/authorize/callback\nexport HIPSTERFY_DB_USER=hipsterfy\nexport HIPSTERFY_DB_PASSWORD=hunter2\nexport HIPSTERFY_JOBQUEUE_PASSWORD=hunter2\nsudo docker-compose -p hipsterfy-dev up --build\n```\n\nDocker Compose is useful for fully tearing down and setting up new instances for testing. You can completely tear down a Docker Compose deployment with:\n\n```bash\nsudo docker-compose -p hipsterfy-dev down --volumes\n```\n\n#### Building the base image locally\n\nThe application Docker image uses a separate base image with built dependencies for caching purposes. Normally, you can pull this image off of the public image on the GitHub Package Registry.\n\nIf you'd like to build this image locally, you can also run:\n\n```bash\nsudo docker build \\\n  -f ./images/hipsterfy-base/Dockerfile \\\n  -t docker.pkg.github.com/liftm/hipsterfy/hipsterfy-base:sha-15c9c5c \\\n  .\n```\n\nMake sure you tag the image correctly! The image tag name must line up with the base `FROM` image used by `images/hipsterfy/Dockerfile`.\n\n### Generating documentation\n\nRun Haddock to generate documentation for both the current project and its dependencies.\n\n```bash\ncabal haddock --haddock-all --enable-documentation\n```\n\nThe output will have a line similar to:\n\n```bash\nDocumentation created:\n.../hipsterfy/dist-newstyle/build/x86_64-linux/ghc-8.8.3/hipsterfy-0.1.0.0/noopt/doc/html/hipsterfy/index.html\n```\n\nOpen this file in your browser to view the documentation.\n\n### Running tests\n\nAutomated integration tests require user access tokens in order to test that they work.\n\n```bash\ncabal test --test-show-details=streaming --test-options='--access_token=XXXX'\n```\n\n#### Retrieving an access token\n\nRun `hipsterfy-tools get-access-token` to retrieve a user access token for testing.\n\n```bash\ncabal run hipsterfy-tools -- get-access-token --db 'postgresql://hipsterfy:hunter2@localhost:5432' --client_id XXXX --client_secret XXXX USER_SPOTIFY_ID\n```\n\n### Formatting code\n\nFor code, use [Ormolu](https://github.com/tweag/ormolu). For `hipsterfy.cabal`, use [`cabal-fmt`](https://github.com/phadej/cabal-fmt).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felldritch%2Fhipsterfy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felldritch%2Fhipsterfy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felldritch%2Fhipsterfy/lists"}