While each provider has its own authentication requirements, the bot will at minimum require a Discord bot. To create one, follow the steps below:
- Create a new Discord bot with the following scopes:
bot
Send Messages
Read Messages
- Enable the
Message Content
toggle underPrivileged Gateway Intents
- Invite the bot to your server using the following URL (change the
client ID to your bot's client ID).
https://discord.com/api/oauth2/authorize?client_id=<client_id>&permissions=3072&scope=bot
- Generate a Bot Token and take note of it.
Set the following environment variables:
MIKU_DISCORD_TOKEN="<Discord Bot Token From Step 3>"
# Optional: Limit to single channel.
MIKU_DISCORD_CHANNEL_ID="<Discord Channel ID>"
Below is specific instructions/requirements for a provider to be enabled.
- Create a new Spotify app following the instructions here.
- Take note of the Client ID and Client Secret.
Set the following environment variables:
MIKU_SPOTIFY_CLIENT_ID="<Client ID>"
MIKU_SPOTIFY_CLIENT_SECRET="<Client Secret>"
Note: Currently the API token will expire every 6 months and need to be regenerated. This will eventually be automated.
- Create a bew media identifier following the instructions here.
- Ensure you downloaded a
.p8
and have your Team ID and Key ID ready. - Run the following command to generate a token:
go run github.com/minchao/go-apple-music/examples/token-generator@latest \ -l 15777000 -t "<Team_ID>" -pf "$HOME/Downloads/AuthKey_<Key_ID>.p8" \ -k "<Key_ID>"
Set the following environment variables:
MIKU_APPLE_MUSIC_API_TOKEN="<Generated Token From Step 3>"
- Create a new Tidal app at the App Dashboard.
- Take note of the Client ID and Client Secret.
Set the following environment variables:
MIKU_TIDAL_CLIENT_ID="<Client ID>"
MIKU_TIDAL_CLIENT_SECRET="<Client Secret>"
Setup a .env.development
using the provider documentation above.
Reference .env.example
to see all available options.
Export env vars from .env.development
:
set -o allexport && source .env.development && set +o allexport
Adding a new provider is fairly straight forward. The provider interface is only concerned with two things:
- Finding a song by URL
- Searching for a song
The interface is defined in the internal/streamingproviders
package.
The implementation of each function should be pretty straight forward, but there are some things that can be good to know:
- Searching for a song should be done using the song's ISRC. This is the most accurate (and easiest) way to find a song. However, some providers may not support searching by it, or it may be empty on the song. In this case, you can use the song's name and artist to search for it. This is less accurate, but should work in most cases.
- When implementing the
Info
function, try to set all fields. This will result in the best experience using the provider, but also the most performant. - Errors returned by all functions do NOT terminate the program, instead they disqualify the provider. So, keep that in mind. Returning errors is essentially a good thing to do, while not returning them could cause a bad user-experience if bad data is returned.
- The
New
function of a provider should fail if there is not enough information to successfully instantiate the provider. For example, check auth configuration here. If it's invalid, fail. This will log a warning to the user but otherwise not terminate the program.
Once you've implemented the provider, you can enable it by default by
adding it to the New
function in internal/handler/handler.go
. The
default providers are instantiated there to prevent an import cycle.
GPL-3.0