TwitchSongRequests
Integrate Twitch channel point rewards directly with a user's Spotify player.
Configure a channel point reward to accept a Spotify song URL, and enqueue
the song in the user's current playing session.
Inspiration
This project was inspired by Kaije, because their
Twitch channel has a channel point reward for requesting a song on Spotify. On that
fateful day, I requested multiple songs in quick succession, and they told me to hold
off on requesting songs because they have to stop working on art in order to manually
copy the Spotify URIs I was sending, in order to queue the songs in their Spotify
player. Between jobs, I coded up an initial proof of concept and the rest is history.
For Users
Update 2023-05-19
Signing up now automatically creates a custom reward with a default cost and title.
This can be updated manually to fit your own needs. No more need to use a keyword in
the reward title! Thanks @rosethornttv for the feedback!
How do I sign up?
- Navigate to the site: https://twitchsongrequests-production.up.railway.app
- Authorize the service with Twitch
- Authorize the service with Spotify
- If it worked, you should see a
Subscribe
and Revoke Access
button
- Click
Subscribe
. If successful, you should see the UI update accordingly
- Submit an onboarding request on this GitHub project, and I will manually allowlist your Spotify account to let you access the service (this is a limitation on Spotify, not on me)
- After you are onboarded, go to your Creator Dashboard > Viewer Rewards > Channel Points > Manage Rewards & Challenges
- Scroll down to find
Spotify Song Request
in the Custom Rewards section and enable the reward - you can edit the amount of channel points, too.
- That's all! Start submitting Spotify URLs with the channel point reward!
From Spotify
We appreciate your interest and efforts in using Spotify's open platform to innovate and build interesting integrations. However, after reviewing we found that your app does not comply with our terms and conditions for the following reasons:
The product or service is integrated with streams or content from another service. The application is integrated with other services (e.g. Twitch) in a way that is prohibited according to section III in our Developer Policy .
As much as I would love to make this more broadly accessible, looks like it goes against their ToS. This means that there will be limited access to the service, since I have to manually allowlist users. If you really want to use it, please sign up via the above steps.
What happens after all 25 slots are taken?
I am working on figuring out how to audit usage of my service, so that I can
give priority to streamers that would actually use it. Even if the service is
at capacity, please still go through all of the onboarding steps. I will
evaluate onboarding newer users first-in-first-out, so getting in line early
is to your own benefit!
How do I use it?
- Open Spotify on your computer
- Navigate to your Twitch channel
- Start playing music on Spotify (the service needs an "active" player to work)
- Find your favorite song on Spotify, copy the URI - (Now supports searching songs with keywords! #218)
- Navigate to the Twitch channel, and find the song request reward (the default title is
Spotify Song Request
)
- Submit the Spotify URI as part of the reward redemption, e.g.: https://open.spotify.com/track/6mfiGqZw4AqXA1nqo3EzIF
- If your Spotify player has queued the song, you're good!
- If your player did not queue the song, make sure you copied the URL correctly, and use the right Channel Point reward
- If you are pretty sure you didn't mess anything up, make an issue here
- If you want to allow your viewers to submit song requests for explicit songs, you have to opt in to this by updating your preferences
- If you want to limit the length of the songs chatters can submit, specify the max song length in seconds in your preferences. Any value less than or equal to zero means any song length is allowed
- If you want to display your song queue (current playing, and next two songs)
on your stream, use the link shown on the page for the OBS browser source. Feel
free to override the CSS with your own custom CSS to make it your own. The page
auto refreshes every 10 seconds.
Demo
Who can use it?
In order to use custom channel point rewards, you must be an affiliate or partner
streamer.
The Spotify account used must have Spotify Premium. If it turns out you do not
have Spotify Premium and you are onboarded but fail to queue songs because of
that, I will take the liberty of removing you from the allowed users in order to
give a chance to other users who want to use the service.
How do I stop using it?
- Navigate to the site: https://twitchsongrequests-production.up.railway.app
- If you are fully authenticated, you should see a
Revoke Access
button
- Click it. This will revoke access to Twitch, which means the application won't receive new channel point redemptions
- Navigate to your Spotify account to revoke access for the service. This can't be done by the service, because they don't expose an API for it. See here for why.
- You're done!
This was working but isn't anymore. What happened?
In order to better accommodate people who want to use this project, I am going to start actively revoking access
to streamers that have not used it in 30 days. Personally, I think it sucks, but it's the only way to fairly keep
up with demand considering I am only allowed to serve 25 users. I will keep track of Twitch users that I revoke access to
via the CHANGELOG
file.
Query ran on the database to get Twitch IDs
select distinct broadcaster_id from messages
where broadcaster_id != ''
and success = 1
and age(messages.created_at) > 30 * INTERVAL '1 day'
except select distinct broadcaster_id from messages
where broadcaster_id != ''
and age(messages.created_at) <= 30 * INTERVAL '1 day';
So the criteria are:
- Had at least 1 successful song request redeemed more than 30 days ago
- Has not had ANY redeems in the past 30 days
This allows for errors such as issues with the API, credentials, etc in the past 30 days, because
at least it was attempted.
API call to get usernames
# for each user ID
twitch token
twitch api get users -q id=$ID
If you believe that I revoked your access in error, please feel free to open a GitHub issue to appeal it, otherwise
you'll want to submit a new onboarding request.
If you want to have better control over this and are willing to host the project yourself, I will be writing up
a guide on how to self-host. TBD
How does it work?
The TwitchSongRequests service will authorize to your Twitch account so that the
service can listen for channel point redemption events from your channel. Once the
service receives an event, it will process that event in order to queue the given
Spotify song into your connected Spotify player.
The service requires access to read Twitch channel point redemptions, and also needs
access to modify a user's Spotify playback state. The Twitch access is needed in order
to allow the service to subscribe to the events, and the Spotify access is required to
queue the song in a user's active player.
The site uses cookies to track whether a user is authenticated or not.
Why not YouTube?
Well, the YouTube API doesn't let you queue videos outside of an iframe player,
which means I would need to embed the player inside my website. Which, I'm not
necessariliy opposed to doing, but that wasn't the original point of this.
If you want this feature, react and comment on this issue
Support the Project
I'm paying to host this service completely out of pocket. If you would like to help
pitch in for the cost of hosting (it's not that much right now), please let me know
and I'll set up a way to contribute in that way.
For Developers
Running the project
Run the project locally:
go run main.go
# or
go build .
./twitchsongrequests
Required variables
Name |
Purpose |
PORT |
Override default port for the HTTP server |
DATABASE_URL |
PostgresDB URL to connect to |
SITE_REDIRECT_URL |
URL for the base path for the main site |
TWITCH_SECRET |
Passphrase to verify subscription requests for Twitch EventSub |
TWITCH_CLIENT_ID |
Twitch app OAuth client ID |
TWITCH_CLIENT_SECRET |
Twitch app OAuth client secret |
TWITCH_STATE |
Twitch app OAuth state key |
TWITCH_REDIRECT_URL |
Twitch OAuth redirect URL |
MOCK_SERVER_URL |
Arbitrary mock URL for local testing with Twitch CLI mock server |
SPOTIFY_CLIENT_ID |
Spotify app OAuth client ID |
SPOTIFY_CLIENT_SECRET |
Spotify app OAuth client secret |
SPOTIFY_REDIRECT_URL |
Spotify OAuth redirect URL |
SPOTIFY_STATE |
Spotify app OAuth state key |
ONBOARDED_USERS |
Number of onboarded users to display stats for |
ALLOWED_USERS |
Number of users that are allowed to be onboarded |
Testing
Unit testing
go test ./... -cover -v -timeout 10s -short
Integration testing
Integration testing for Postgres queries is done via GitHub actions.
Take a look at the .github/workflows/ci.yml
file for how they are run.
Technically they can be run locally by standing up a Postgres db and injecting
the same test data into a local instance.
Set up Twitch CLI
Use the Twitch CLI for local development.
Set up an EventSub subscription for testing end-to-end
Note: the Twitch CLI mock server does not support EventSub, so it can not be
used for local testing of creating subscriptions. We must use the real API
Authenticate with the Twitch CLI:
twitch token
Then, use the app access token from the above command to authentication.
Get your own user payload, and note the user ID from the response.
twitch api get /users -q login=YourTwitchUsername
The response will look something like this:
{
"data": [
{
"broadcaster_type": "affiliate",
"created_at": "2015-11-03T23:03:04Z",
"description": "A description about the user",
"display_name": "SaxyPandaBear",
"id": "1234567890",
"login": "saxypandabear",
"offline_image_url": "https://some-image1.png",
"profile_image_url": "https://some-image2.png",
"type": "",
"view_count": 1337
}
]
}
Jot down the id
in the JSON response body
Subscribe to the channel point reward redemption event, replacing the USER_ID
,
TOKEN
, CLIENT_ID
, CALLBACK_URL
, and SUB_SECRET
with your own values.
curl -X POST https://api.twitch.tv/helix/eventsub/subscriptions \
-H 'Authorization: Bearer $TOKEN' \
-H 'Client-Id: $CLIENT_ID' \
-H 'Content-Type: application/json' \
-d '{"type": "channel.channel_points_custom_reward_redemption.add", "version": "1", "condition": {"broadcaster_user_id": "$USER_ID"}, "transport": {"method": "webhook", "callback":"$CALLBACK_URL", "secret": "$SUB_SECRET"}}'
Make a note of the id
value from the response.
Verify that the subscription was made successfully:
twitch api get /eventsub/subscriptions -q user_id=$USER_ID
The response will look like:
{
"data": [
{
"condition": {
"broadcaster_user_id": "1234567890",
"reward_id": ""
},
"cost": 0,
"created_at": "2023-01-29T04:23:21.008351071Z",
"id": "abc-123-def-456",
"status": "webhook_callback_verification_pending",
"transport": {
"callback": "https://this-service/endpoint",
"method": "webhook"
},
"type": "channel.channel_points_custom_reward_redemption.add",
"version": "1"
}
],
"pagination": {
"cursor": ""
},
"total": 1
}
Run local API server to handle callback
Start the server locally
export TWITCH_CLIENT_ID=$CLIENT_ID
go run main.go
Make sure that the server is up
curl localhost:8080/
Create and send a test webhook payload to the local server
twitch event trigger add-redemption -s $SUB_SECRET -F http://localhost:8080/callback
Check the server logs to confirm that the event was received and processed.
2022/09/05 10:49:46 verified signature for subscription
2022/09/05 10:49:46 52f644c8-33da-4a30-bc81-beccb4cb678a Test Reward from CLI
Cleanup
After testing, clean up the EventSub subscription:
twitch api get /eventsub/subscriptions
# jot down the relevant EventSub subscription ID
curl -X DELETE https://api.twitch.tv/helix/eventsub/subscriptions?id=$SUB_ID -H 'Authorization: Bearer $TOKEN' -H 'Client-Id: $CLIENT_ID'
Deploying
This service is deployed directly to Railway, via the supplied Dockerfile at the root of the repo.