Json encoder server-side; Select your own lyrics result
This commit is contained in:
@ -201,10 +201,18 @@ class HttpHandler(tornado.web.RequestHandler):
|
||||
# when our request calls subsequent external requests (eg Spotify, Genius).
|
||||
# We don't need to wrap non-HTTPResponse responses as these are dicts
|
||||
if isinstance(response, tornado.httpclient.HTTPResponse):
|
||||
|
||||
# Digest JSON resposes into JSON
|
||||
content_type = response.headers.get('Content-Type')
|
||||
if content_type.startswith('application/json') or content_type.startswith('text/json'):
|
||||
body = json.loads(response.body)
|
||||
else:
|
||||
body = response.body
|
||||
|
||||
response = {
|
||||
'response_code': response.code,
|
||||
'response_message': response.reason,
|
||||
'response': response.body
|
||||
'response': body
|
||||
}
|
||||
|
||||
self.write(response)
|
||||
|
||||
@ -16,15 +16,20 @@ const sendRequest = (dispatch, getState, endpoint) => {
|
||||
var loader_key = helpers.generateGuid();
|
||||
dispatch(uiActions.startLoading(loader_key, 'genius_'+endpoint));
|
||||
|
||||
var url = endpoint;
|
||||
if (!url.startsWith('http')){
|
||||
url = 'https://api.genius.com/'+url;
|
||||
}
|
||||
|
||||
var config = {
|
||||
method: 'POST',
|
||||
cache: false,
|
||||
timeout: 30000,
|
||||
headers: {
|
||||
Authorization: 'Bearer 2AGP9sfzKQcxfKSZuGa_3lqsDIpuOiTGT7-vhJYcKaaDjHIIA2HICsxXCiC30Xxi'
|
||||
Authorization: 'Bearer nBNNEFekix8BOsfPyfK7LtX-CaUz7L7ak92qC3GfMAIQi8eWjuwb4P8SUxK1K-iY'
|
||||
},
|
||||
data: JSON.stringify({
|
||||
url: 'https://genius.com/'+endpoint
|
||||
url: url
|
||||
}),
|
||||
url: '//'+getState().mopidy.host+':'+getState().mopidy.port+'/iris/http/proxy_request'
|
||||
};
|
||||
@ -47,17 +52,26 @@ const sendRequest = (dispatch, getState, endpoint) => {
|
||||
})
|
||||
}
|
||||
|
||||
export function getTrackLyrics(track){
|
||||
/**
|
||||
* Extract lyrics from a page
|
||||
* We don't get the lyrics in the API, so we need to 'scrape' the HTML page instead
|
||||
*
|
||||
* @param uri = track uri
|
||||
* @param result = lyrics result (title, url)
|
||||
**/
|
||||
export function getTrackLyrics(uri, url){
|
||||
return (dispatch, getState) => {
|
||||
|
||||
var endpoint = '';
|
||||
for (var i = 0; i < track.artists.length; i++){
|
||||
endpoint += track.artists[i].name+' ';
|
||||
}
|
||||
endpoint += track.name+' lyrics';
|
||||
endpoint = endpoint.replace(/\s+/g, '-').toLowerCase();
|
||||
dispatch({
|
||||
type: 'TRACK_LOADED',
|
||||
key: uri,
|
||||
track: {
|
||||
lyrics: null,
|
||||
lyrics_url: null
|
||||
}
|
||||
});
|
||||
|
||||
sendRequest(dispatch, getState, endpoint)
|
||||
sendRequest(dispatch, getState, url)
|
||||
.then(
|
||||
response => {
|
||||
var html = $(response);
|
||||
@ -75,16 +89,17 @@ export function getTrackLyrics(track){
|
||||
|
||||
dispatch({
|
||||
type: 'TRACK_LOADED',
|
||||
key: track.uri,
|
||||
key: uri,
|
||||
track: {
|
||||
lyrics: lyrics_html
|
||||
lyrics: lyrics_html,
|
||||
lyrics_url: url
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
error => {
|
||||
dispatch(coreActions.handleException(
|
||||
'Could not get track lyrics',
|
||||
'Could not extract track lyrics',
|
||||
error
|
||||
));
|
||||
}
|
||||
@ -92,26 +107,36 @@ export function getTrackLyrics(track){
|
||||
}
|
||||
}
|
||||
|
||||
export function getTrackInfo(track){
|
||||
export function findTrackLyrics(track){
|
||||
return (dispatch, getState) => {
|
||||
|
||||
var query = '';
|
||||
for (var i = 0; i < track.artists.length; i++){
|
||||
query += track.artists[i].name+' ';
|
||||
}
|
||||
query += track.artists[0].name+' ';
|
||||
query += track.name;
|
||||
query = query.toLowerCase();
|
||||
query = query.replace(/\([^)]*\) */g, ''); // anything in circle-braces
|
||||
query = query.replace(/\([^[]*\] */g, ''); // anything in square-braces
|
||||
query = query.replace(/[^A-Za-z0-9\s]/g, ''); // non-alphanumeric
|
||||
|
||||
sendRequest(dispatch, getState, 'search?q='+encodeURIComponent(query))
|
||||
.then(
|
||||
response => {
|
||||
if (response.response.hits && response.response.hits.length > 0){
|
||||
var lyrics_results = [];
|
||||
for (var i = 0; i < response.response.hits.length; i++){
|
||||
lyrics_results.push({
|
||||
title: response.response.hits[i].result.full_title,
|
||||
url: response.response.hits[i].result.url
|
||||
});
|
||||
}
|
||||
dispatch({
|
||||
type: 'TRACK_LOADED',
|
||||
key: track.uri,
|
||||
track: {
|
||||
annotations: response.response.hits[0].result
|
||||
lyrics_results: lyrics_results
|
||||
}
|
||||
});
|
||||
dispatch(getTrackLyrics(track.uri, lyrics_results[0].url));
|
||||
}
|
||||
},
|
||||
error => {
|
||||
|
||||
@ -158,7 +158,7 @@ function refreshToken(dispatch, getState){
|
||||
.then(
|
||||
response => {
|
||||
if (response.response_code == 200){
|
||||
var token = JSON.parse(response.response);
|
||||
var token = response.response;
|
||||
token.token_expiry = new Date().getTime() + (token.expires_in * 1000 );
|
||||
token.source = 'mopidy';
|
||||
dispatch({
|
||||
|
||||
@ -52,7 +52,7 @@ class Track extends React.Component{
|
||||
|
||||
// We don't have lyrics, and we have just received our artists
|
||||
if (!nextProps.track.lyrics && !this.props.track.artists && nextProps.track.artists){
|
||||
this.props.geniusActions.getTrackLyrics(nextProps.track);
|
||||
this.props.geniusActions.findTrackLyrics(nextProps.track);
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,6 +93,38 @@ class Track extends React.Component{
|
||||
this.props.mopidyActions.playURIs([this.props.params.uri], this.props.params.uri)
|
||||
}
|
||||
|
||||
renderLyricsSelector(){
|
||||
if (!this.props.track.lyrics_results){
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="field lyrics-selector">
|
||||
<div className="input">
|
||||
<select
|
||||
onChange={e => this.props.geniusActions.getTrackLyrics(this.props.track.uri, e.target.value)}>
|
||||
{
|
||||
this.props.track.lyrics_results.map(result => {
|
||||
return (
|
||||
<option
|
||||
key={result.url}
|
||||
value={result.url}
|
||||
defaultValue={result.url == this.props.track.lyrics_url}
|
||||
>
|
||||
{result.title}
|
||||
</option>
|
||||
)
|
||||
})
|
||||
}
|
||||
</select>
|
||||
<div className="description">
|
||||
Switch to another lyrics seach result
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderLyrics(){
|
||||
if (helpers.isLoading(this.props.load_queue,['genius_'])){
|
||||
return (
|
||||
@ -101,9 +133,22 @@ class Track extends React.Component{
|
||||
</div>
|
||||
);
|
||||
} else if (!this.props.track.lyrics){
|
||||
return <div className="lyrics"><p className="grey-text"><em>No lyrics available</em></p></div>
|
||||
return (
|
||||
<div className="lyrics">
|
||||
<div className="content">
|
||||
<em className="grey-text">No lyrics available</em>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return <div className="lyrics" dangerouslySetInnerHTML={{__html: this.props.track.lyrics}}></div>
|
||||
return (
|
||||
<div className="lyrics">
|
||||
<div className="content" dangerouslySetInnerHTML={{__html: this.props.track.lyrics}}></div>
|
||||
<div className="origin grey-text">
|
||||
Origin: <a href={this.props.track.lyrics_url} target="_blank">{this.props.track.lyrics_url}</a>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,6 +206,7 @@ class Track extends React.Component{
|
||||
{this.props.slim_mode ? null : <ContextMenuTrigger onTrigger={e => this.handleContextMenu(e)} />}
|
||||
</div>
|
||||
|
||||
{this.renderLyricsSelector()}
|
||||
{this.renderLyrics()}
|
||||
|
||||
</div>
|
||||
|
||||
@ -29,8 +29,13 @@ select {
|
||||
}
|
||||
|
||||
select {
|
||||
max-width: 100%;
|
||||
|
||||
option {
|
||||
background: $white;
|
||||
color: $darkest_grey;
|
||||
max-width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -37,12 +37,23 @@ main .track-view {
|
||||
}
|
||||
}
|
||||
|
||||
.lyrics {
|
||||
p {
|
||||
line-height: 0.8em;
|
||||
.lyrics {
|
||||
.content {
|
||||
padding-bottom: 20px;
|
||||
|
||||
*,
|
||||
& * {
|
||||
font-size: 18px;
|
||||
line-height: normal;
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.lyrics-selector {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
@include responsive($bp_medium){
|
||||
padding-top: 0;
|
||||
padding-left: 10px;
|
||||
|
||||
Reference in New Issue
Block a user