This is a java wrapper for the Genius API.
Feature overview:
- Supports: Songs & Artists, Annotations & Referents, Web Pages, Search
- Lyrics searching
- Uses Reactor
- Basic authentication (Client Access Token & Access Token)
- Compiled for
Java 11
Be sure to replace the VERSION key below with the version shown above!
<repository>
<id>spoocyDev-releases</id>
<name>Coding Stube Repository</name>
<url>https://repo.coding-stube.de/releases</url>
</repository><dependency>
<groupId>dev.spoocy.genius</groupId>
<artifactId>GeniusAPI</artifactId>
<version>VERSION</version>
</dependency>- Please also check out the Genius API Documentation.
- Make sure you know how Reactor works!
- You will need to authenticate using one of the methods below before making any requests to the Genius API.
Please see Genius's Authentication Documentation for more information about Authentication.
Important
You will need to create a Genius API Client. You can do so at https://genius.com/api-clients
There are two types of access tokens you can use to authenticate to the Genius API:
- Client Access Token: Use this if your application doesn't include user-specific behavior (read-only endpoints that don't require scopes).
- User Access Token (OAuth Authorization Code flow): Use this if you need to make requests on behalf of individual users (requires scopes).
- client_id: Your application's Client ID
- client_secret: Your application's Client Secret
- client_access_token: Your application's Client Access Token (You can get a client access token by clicking "Generate Access Token" on the API Client management page.)
GeniusClient client = GeniusClient.builder()
.clientId("your_client_id") // Your application's Client ID
.clientSecret("your_client_secret") // Your application's Client Secret
.accessToken("your_client_access_token") // Your application's Client Access Token
.build();Used for making API calls on behalf of individual users.
- client_id: Your application's Client ID
- client_secret: Your application's Client Secret
- redirect_uri: The URI Genius will redirect the user to after they've authorized your application; it must be the same as the one set for the API Client on the management page
- state: A value that will be returned with the code redirect for maintaining arbitrary state through the authorization process
- scopes: A list of scopes of access to request from the user (see Genius Scopes for more information)
- Create the GeniusClient with your client_id and client_secret:
GeniusClient client = GeniusClient.builder()
.clientId("your_client_id") // Your application's Client ID
.clientSecret("your_client_secret") // Your application's Client Secret
.build();- Build the authorization URI and redirect the user to it:
// Build the authorization URI for the user to authorize your application
URI authorizationUri = client.authorizationCodeUri(
SECRET_STATE, // A secret state value
"http://your_redirect_uri.com", // Your redirect URI
Scope.ME, Scope.VOTE // The scopes you are requesting
)
.block(); // Example only. Avoid blocking in production code.- Request an Access Token using the Authorization Code received from the redirect:
GeniusAccessToken token = client.accessToken(
code, // The Authorization Code received from the redirect
"http://your_redirect_uri.com", // Set your Redirect URI (the same as above!!!)
Scope.ME, Scope.VOTE // Set the required Scopes (the same as above!!!)
).block();
client.setAccessToken(token); // Set the Authorization Code, otherwise no requests can be madeRequests return Mono instances from Reactor to wait for results.
The following show very basic examples of how to use the various endpoints.
client.getAnnotation(3037171L, TextFormat.PLAIN, TextFormat.HTML) // annotation id
.doOnError(e -> System.out.println("Error: " + e.getMessage()))
.subscribe(data -> System.out.println("Body: " + data.getAnnotation().getBody(TextFormat.PLAIN)));Request Builder: client.annotation()
client.getReferentsBySongId(378195L, 5, 1, TextFormat.PLAIN) // with song id
.doOnError(e -> System.out.println("Error: " + e.getMessage()))
.subscribe(data -> System.out.println("Amount: " + data.getReferents().size()));
client.getReferentsByCreatedBy(16775L, 5, 1, TextFormat.PLAIN) // with creator id
.doOnError(e -> System.out.println("Error: " + e.getMessage()))
.subscribe(data -> System.out.println("Amount: " + data.getReferents().size()));
client.getReferentsByWebPage(10347L, 5, 1, TextFormat.PLAIN) // with web page id
.doOnError(e -> System.out.println("Error: " + e.getMessage()))
.subscribe(data -> System.out.println("Amount: " + data.getReferents().size()));Request Builder: client.referents()
client.getSong(
378195L, // song id
TextFormat.PLAIN, TextFormat.HTML // optional description formats
)
.doOnError(e -> {
System.out.println("Error while searching for Song: " + e.getMessage());
e.printStackTrace();
})
.subscribe(song -> {
System.out.printf("Title: %s%n", song.getTitle());
System.out.printf("Description: %s%n", song.getDescription(TextFormat.PLAIN));
});Request Builder: client.song()
client.getArtist(
16775L, // artist id
TextFormat.HTML // optional description formats
)
.doOnError(e -> {
System.out.println("Error while searching for Artist: " + e.getMessage());
e.printStackTrace();
})
.subscribe(artist -> {
System.out.printf("Name: %s%n", artist.getName());
System.out.printf("Description: %s%n", artist.getDescription(TextFormat.PLAIN.HTML));
});Request Builder: ```client.artist()
client.getArtistSongs(16775L, Sort.POPULARITY, 5, 1)
.doOnError(e -> System.out.println("Error: " + e.getMessage()))
.subscribe(data -> System.out.println("Amount: " + data.getSongs().size()));Request Builder: client.artistSongs()
client.getWebPage("https://docs.genius.com", null, null)
.doOnError(e -> System.out.println("Error: " + e.getMessage()))
.subscribe(data -> System.out.println("Web Page ID: " + data.getId()));Request Builder: client.webPagesLookup()
client.getAccount(TextFormat.PLAIN)
.doOnError(e -> System.out.println("Error: " + e.getMessage()))
.subscribe(data -> System.out.println("Account Name: " + data.getName()));client.search("Kendrick Lamar")
.doOnError(e -> System.out.println("Error while searching: " + e.getMessage()))
.subscribe(search -> {
if (search.getHits().isEmpty()) {
System.out.println("No results found!");
return;
}
Search.Hit first = search.getHits().get(0);
System.out.printf("Title: %s%n", first.getResult().getTitle());
System.out.printf("Artist: %s%n", first.getResult().getArtistNames());
});Request Builder: client.search()
client.getLyricsByQuery("Kendrik Lamar Humble").
doOnError(e -> System.out.println("Error while getting lyrics: " + e.getMessage()))
.subscribe(lyrics -> System.out.println(lyrics.getPlain()));
String url = "https://genius.com/Kendrick-lamar-humble-lyrics";
client.getLyricsByUrl(url)
.doOnError(e -> System.out.println("Error while getting lyrics: " + e.getMessage()))
.subscribe(lyrics -> System.out.println(lyrics.getPlain()));
// Or build the request manually:
client.lyrics()
.url(url) // e.g. "https://genius.com/Kendrick-lamar-humble-lyrics" (query will be ignored if url is set)
.path(url) // e.g. "Kendrick-lamar-humble-lyrics" (query will be ignored if url is set)
.query(url) // e.g. "Kendrick Lamar Humble" (Search Query)
.build()
.doOnError(e -> System.out.println("Error while getting lyrics: " + e.getMessage()))
.subscribe(lyrics -> System.out.println(lyrics.getPlain()));Request Builder: client.lyrics()
GeniusException: Could not find Lyrics Container. This happens when Genius changes their website. Report this to the developer and/or try to set the container ids directly via the LyricsScraper.
This means that the library could not find the lyrics container on the website because their names changed.
Try using unknownContainerNames() in the lyrics request builder to attempt to find the correct lyrics:
client.lyrics()
.url(url)
.unknownContainerNames() // try this
.build()
.doOnError(e -> System.out.println("Error while getting lyrics: " + e.getMessage()))
.subscribe(lyrics -> System.out.println(lyrics.getPlain()));This will scan the whole site and guess the container names. This does not guarantee successful extraction, but may work. This will result in a slower extraction process so it should on be used when the lyrics extraction fails with the default Extractor.
You can also try to create your own extractor implementing the 'LyricsExtractor' interface or set the container names directly:
LyricsExtractor extractor = new DirectLyricsExtractor.Builder()
.lyrics_container("lyrics_container_name")
.lyrics_container_header("lyrics_container_header_name")
.lyrics_title_container("lyrics_title_container_name")
.build();You will have to inspect the Genius website in order to find the new container ids.