Compare commits
7 Commits
496ff9bb52
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| e0b6be24c1 | |||
| cd3575d514 | |||
| 77e8546baa | |||
| 122d328de4 | |||
| f3846a2311 | |||
| 0cf1c52743 | |||
| fcce6a8d11 |
+20
-9
@@ -1,23 +1,34 @@
|
|||||||
FROM alpine:3.22.1 AS build
|
FROM alpine:3.22.1 AS build
|
||||||
|
LABEL maintainer="Ross Stewart <rosskouk@gmail.com>"
|
||||||
|
LABEL org.opencontainers.image.source=https://github.com/rosskouk/asknavidrome
|
||||||
|
|
||||||
RUN apk add python3 py3-pip git build-base python3-dev libffi-dev openssl-dev
|
RUN apk add python3 py3-pip git build-base python3-dev libffi-dev openssl-dev
|
||||||
|
|
||||||
WORKDIR /opt
|
WORKDIR /opt
|
||||||
RUN pwd
|
|
||||||
RUN python3 -m venv env
|
RUN python3 -m venv env
|
||||||
RUN ls -la
|
|
||||||
RUN git clone https://g.nunks.org/nunks/asknavidrome-cafofo.git
|
RUN git clone https://github.com/rosskouk/asknavidrome.git
|
||||||
RUN ls -la asknavidrome-cafofo
|
|
||||||
WORKDIR /opt/asknavidrome-cafofo
|
WORKDIR /opt/asknavidrome
|
||||||
RUN pwd
|
|
||||||
RUN ls -la
|
|
||||||
RUN source ../env/bin/activate && pip --no-cache-dir install wheel && pip --no-cache-dir install -r skill/requirements-docker.txt
|
RUN source ../env/bin/activate && pip --no-cache-dir install wheel && pip --no-cache-dir install -r skill/requirements-docker.txt
|
||||||
|
|
||||||
|
|
||||||
FROM alpine:3.22.1
|
FROM alpine:3.22.1
|
||||||
|
LABEL maintainer="Ross Stewart <rosskouk@gmail.com>"
|
||||||
|
LABEL org.opencontainers.image.source=https://github.com/rosskouk/asknavidrome
|
||||||
|
|
||||||
RUN apk add python3
|
RUN apk add python3
|
||||||
|
|
||||||
COPY --from=build /opt/env /opt/env
|
COPY --from=build /opt/env /opt/env
|
||||||
COPY --from=build /opt/asknavidrome-cafofo/skill /opt/asknavidrome/
|
COPY --from=build /opt/asknavidrome/skill /opt/asknavidrome/
|
||||||
|
|
||||||
WORKDIR /opt/asknavidrome
|
WORKDIR /opt/asknavidrome
|
||||||
|
|
||||||
# Activate Python Virtual Environment
|
# Activate Python Virtual Environment
|
||||||
ENV PATH="/opt/env/bin:$PATH"
|
ENV PATH="/opt/env/bin:$PATH"
|
||||||
|
|
||||||
EXPOSE 5000
|
EXPOSE 5000
|
||||||
ENTRYPOINT ["python3", "app.py"]
|
|
||||||
|
ENTRYPOINT ["python3", "app.py"]
|
||||||
+50
-58
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"interactionModel": {
|
"interactionModel": {
|
||||||
"languageModel": {
|
"languageModel": {
|
||||||
"invocationName": "cafofo music",
|
"invocationName": "navisonic",
|
||||||
"intents": [
|
"intents": [
|
||||||
{
|
{
|
||||||
"name": "AMAZON.CancelIntent",
|
"name": "AMAZON.CancelIntent",
|
||||||
@@ -40,8 +40,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"samples": [
|
"samples": [
|
||||||
"tocar músicas da {artist}",
|
"play songs by {artist}",
|
||||||
"tocar músicas do {artist}"
|
"play music by {artist}"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -65,20 +65,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"samples": [
|
"samples": [
|
||||||
"Tocar o album {album}",
|
"Play the album {album}",
|
||||||
"Tocar o album {album} do {artist}",
|
"Play the album {album} by {artist}"
|
||||||
"Tocar o album {album} da {artist}",
|
|
||||||
"Tocar o disco {album}",
|
|
||||||
"Tocar o disco {album} do {artist}",
|
|
||||||
"Tocar o disco {album} da {artist}"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "NaviSonicPlayMusicByCurrentAlbum",
|
|
||||||
"slots": [],
|
|
||||||
"samples": [
|
|
||||||
"Tocar mais músicas desse album",
|
|
||||||
"Tocar mais músicas desse disco"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -90,42 +78,49 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"samples": [
|
"samples": [
|
||||||
"Tocar a playlist {playlist}"
|
"Play the {playlist} playlist",
|
||||||
|
"Start the {playlist} playlist"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "NaviSonicSongDetails",
|
"name": "NaviSonicSongDetails",
|
||||||
"slots": [],
|
"slots": [],
|
||||||
"samples": [
|
"samples": [
|
||||||
"O que está tocando",
|
"What is playing",
|
||||||
"Quem está tocando",
|
"Who is singing",
|
||||||
"Quem está cantando",
|
"Who's singing",
|
||||||
"Qual o album dessa música",
|
"What album is this song on",
|
||||||
"Que banda é essa",
|
"What album is this on",
|
||||||
"Que musica é essa",
|
"Which album",
|
||||||
"Que banda é essa"
|
"Which album is this song from",
|
||||||
|
"Which artist is this",
|
||||||
|
"What band is this",
|
||||||
|
"Who sings this song",
|
||||||
|
"Who sings this",
|
||||||
|
"What song is this",
|
||||||
|
"What's playing"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "NaviSonicStarSong",
|
"name": "NaviSonicStarSong",
|
||||||
"slots": [],
|
"slots": [],
|
||||||
"samples": [
|
"samples": [
|
||||||
"Adicionar música aos favoritos",
|
"Add this song to my favourites",
|
||||||
"Adicionar aos favoritos",
|
"Favourite this song",
|
||||||
"Favoritar essa musica",
|
"Like this song",
|
||||||
"Lembrar dessa música",
|
"Add this song to my liked songs",
|
||||||
"Eu gosto dessa música"
|
"Star this song"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "NaviSonicUnstarSong",
|
"name": "NaviSonicUnstarSong",
|
||||||
"slots": [],
|
"slots": [],
|
||||||
"samples": [
|
"samples": [
|
||||||
"Tirar a música dos favoritos",
|
"Remove this song from favourites",
|
||||||
"Tirar dos favoritos",
|
"I don't like this song",
|
||||||
"Desfavoritar a música",
|
"Remove the star from this song",
|
||||||
"Esquecer essa música",
|
"Delete this song from my favourites",
|
||||||
"Eu não gosto dessa música"
|
"Unstar this song"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -141,27 +136,21 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"samples": [
|
"samples": [
|
||||||
"Tocar a música {song} da banda {artist}",
|
"Play the song {song} by the band {artist}",
|
||||||
"Tocar {song} da banda {artist}",
|
"Play {song} by the band {artist}",
|
||||||
"Tocar {song} da {artist}"
|
"Play {song} by {artist}",
|
||||||
]
|
"Play the song {song} by the artist {artist}"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "NaviSonicPlayMusicByCurrentArtist",
|
|
||||||
"slots": [],
|
|
||||||
"samples": [
|
|
||||||
"Tocar mais músicas desse artista",
|
|
||||||
"Tocar mais músicas desse grupo",
|
|
||||||
"Tocar mais músicas dessa banda"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "NaviSonicPlayFavouriteSongs",
|
"name": "NaviSonicPlayFavouriteSongs",
|
||||||
"slots": [],
|
"slots": [],
|
||||||
"samples": [
|
"samples": [
|
||||||
"Tocar favoritos",
|
"Play my starred tracks",
|
||||||
"Tocar meus favoritos",
|
"Play starred tracks",
|
||||||
"Tocar minhas músicas favoritas"
|
"Play starred songs",
|
||||||
|
"Play my starred songs",
|
||||||
|
"Play my favourite songs"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -173,26 +162,29 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"samples": [
|
"samples": [
|
||||||
"Tocar {genre}"
|
"Play {genre} songs",
|
||||||
|
"Play {genre} music"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "NaviSonicPlayMusicRandom",
|
"name": "NaviSonicPlayMusicRandom",
|
||||||
"slots": [],
|
"slots": [],
|
||||||
"samples": [
|
"samples": [
|
||||||
"Tocar seleção aleatória",
|
"Play a selection of music",
|
||||||
"Tocar qualquer coisa",
|
"Play a mix of tracks",
|
||||||
"Tocar mix",
|
"Play a mix of songs",
|
||||||
"Tocar músicas aleatórias"
|
"Play random music",
|
||||||
|
"Play random songs"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "NaviSonicRandomiseQueue",
|
"name": "NaviSonicRandomiseQueue",
|
||||||
"slots": [],
|
"slots": [],
|
||||||
"samples": [
|
"samples": [
|
||||||
|
"randomise the queue",
|
||||||
|
"randomise",
|
||||||
"shuffle",
|
"shuffle",
|
||||||
"shuffle na lista",
|
"shuffle the queue"
|
||||||
"mistura tudo"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -220,4 +212,4 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
-1
@@ -3491,7 +3491,9 @@ embedded in the URI</p>
|
|||||||
<span class="sig-name descname"><span class="pre">ping</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">→</span> <span class="sig-return-typehint"><span class="pre">bool</span></span></span><a class="headerlink" href="#asknavidrome.subsonic_api.SubsonicConnection.ping" title="Link to this definition">#</a></dt>
|
<span class="sig-name descname"><span class="pre">ping</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">→</span> <span class="sig-return-typehint"><span class="pre">bool</span></span></span><a class="headerlink" href="#asknavidrome.subsonic_api.SubsonicConnection.ping" title="Link to this definition">#</a></dt>
|
||||||
<dd><p>Ping a Subsonic API server</p>
|
<dd><p>Ping a Subsonic API server</p>
|
||||||
<p>Verify the connection to a Subsonic compatible API server
|
<p>Verify the connection to a Subsonic compatible API server
|
||||||
is working</p>
|
is working. Enhanced logging has been added to examine the
|
||||||
|
HTTP response returned from the server to assist with troubleshooting
|
||||||
|
connection issues.</p>
|
||||||
<dl class="field-list simple">
|
<dl class="field-list simple">
|
||||||
<dt class="field-odd">Returns<span class="colon">:</span></dt>
|
<dt class="field-odd">Returns<span class="colon">:</span></dt>
|
||||||
<dd class="field-odd"><p>True if the connection works, False if it does not</p>
|
<dd class="field-odd"><p>True if the connection works, False if it does not</p>
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
+27
-130
@@ -42,7 +42,7 @@ logger.addHandler(handler)
|
|||||||
# Get service configuration
|
# Get service configuration
|
||||||
#
|
#
|
||||||
|
|
||||||
logger.info('AskNavidrome 0.9!')
|
logger.info('AskNavidrome 0.10!')
|
||||||
logger.debug('Getting configuration from the environment...')
|
logger.debug('Getting configuration from the environment...')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -222,7 +222,7 @@ class LaunchRequestHandler(AbstractRequestHandler):
|
|||||||
logger.debug('In LaunchRequestHandler')
|
logger.debug('In LaunchRequestHandler')
|
||||||
|
|
||||||
connection.ping()
|
connection.ping()
|
||||||
speech = sanitise_speech_output('Simbora!')
|
speech = sanitise_speech_output('Ready!')
|
||||||
|
|
||||||
handler_input.response_builder.speak(speech).ask(speech)
|
handler_input.response_builder.speak(speech).ask(speech)
|
||||||
return handler_input.response_builder.response
|
return handler_input.response_builder.response
|
||||||
@@ -311,8 +311,7 @@ class NaviSonicPlayMusicByArtist(AbstractRequestHandler):
|
|||||||
artist_lookup = connection.search_artist(artist.value)
|
artist_lookup = connection.search_artist(artist.value)
|
||||||
|
|
||||||
if artist_lookup is None:
|
if artist_lookup is None:
|
||||||
#text = sanitise_speech_output(f"I couldn't find the artist {artist.value} in the collection.")
|
text = sanitise_speech_output(f"I couldn't find the artist {artist.value} in the collection.")
|
||||||
text = sanitise_speech_output(f"Não achei o artista {artist.value} na nossa coleção.")
|
|
||||||
handler_input.response_builder.speak(text).ask(text)
|
handler_input.response_builder.speak(text).ask(text)
|
||||||
|
|
||||||
return handler_input.response_builder.response
|
return handler_input.response_builder.response
|
||||||
@@ -329,8 +328,7 @@ class NaviSonicPlayMusicByArtist(AbstractRequestHandler):
|
|||||||
backgroundProcess = Process(target=queue_worker_thread, args=(connection, play_queue, song_id_list[2:])) # Create a thread to enqueue the remaining tracks
|
backgroundProcess = Process(target=queue_worker_thread, args=(connection, play_queue, song_id_list[2:])) # Create a thread to enqueue the remaining tracks
|
||||||
backgroundProcess.start() # Start the additional thread
|
backgroundProcess.start() # Start the additional thread
|
||||||
|
|
||||||
#speech = sanitise_speech_output(f'Playing music by: {artist.value}')
|
speech = sanitise_speech_output(f'Playing music by: {artist.value}')
|
||||||
speech = sanitise_speech_output(f'Tocando músicas de: {artist.value}')
|
|
||||||
logger.info(speech)
|
logger.info(speech)
|
||||||
|
|
||||||
card = {'title': 'AskNavidrome',
|
card = {'title': 'AskNavidrome',
|
||||||
@@ -341,97 +339,6 @@ class NaviSonicPlayMusicByArtist(AbstractRequestHandler):
|
|||||||
track_details = play_queue.get_next_track()
|
track_details = play_queue.get_next_track()
|
||||||
return controller.start_playback('play', speech, card, track_details, handler_input)
|
return controller.start_playback('play', speech, card, track_details, handler_input)
|
||||||
|
|
||||||
def get_current_song_details():
|
|
||||||
current_track = play_queue.get_current_track()
|
|
||||||
logger.debug(current_track)
|
|
||||||
return {
|
|
||||||
"title": current_track.title,
|
|
||||||
"artist": current_track.artist,
|
|
||||||
"album": current_track.album,
|
|
||||||
"_sanitized": {
|
|
||||||
"title": sanitise_speech_output(current_track.title),
|
|
||||||
"artist": sanitise_speech_output(current_track.artist),
|
|
||||||
"album": sanitise_speech_output(current_track.album)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class NaviSonicPlayMusicByCurrentArtist(AbstractRequestHandler):
|
|
||||||
"""Handle NaviSonicPlayMusicByCurrentArtist Intent
|
|
||||||
|
|
||||||
Plays more music of the current playing Artist
|
|
||||||
"""
|
|
||||||
|
|
||||||
def can_handle(self, handler_input: HandlerInput) -> bool:
|
|
||||||
return is_intent_name('NaviSonicPlayMusicByCurrentArtist')(handler_input)
|
|
||||||
|
|
||||||
def handle(self, handler_input: HandlerInput) -> Response:
|
|
||||||
global backgroundProcess
|
|
||||||
logger.debug('In NaviSonicPlayMusicByCurrentArtist Handler (custom)')
|
|
||||||
if backgroundProcess is not None:
|
|
||||||
backgroundProcess.terminate()
|
|
||||||
backgroundProcess.join()
|
|
||||||
|
|
||||||
t = get_current_song_details() #current "T"rack
|
|
||||||
|
|
||||||
artist_lookup = connection.search_artist(t["artist"])
|
|
||||||
artist_album_lookup = connection.albums_by_artist(artist_lookup[0].get('id'))
|
|
||||||
song_id_list = connection.build_song_list_from_albums(artist_album_lookup, min_song_count)
|
|
||||||
play_queue.clear()
|
|
||||||
|
|
||||||
controller.enqueue_songs(connection, play_queue, [song_id_list[0], song_id_list[1]]) # When generating the playlist return the first two tracks.
|
|
||||||
backgroundProcess = Process(target=queue_worker_thread, args=(connection, play_queue, song_id_list[2:])) # Create a thread to enqueue the remaining tracks
|
|
||||||
backgroundProcess.start() # Start the additional thread
|
|
||||||
|
|
||||||
speech = sanitise_speech_output(f'Tocando mais músicas de {t["artist"]}')
|
|
||||||
logger.info(speech)
|
|
||||||
|
|
||||||
card = {'title': 'AskNavidrome',
|
|
||||||
'text': speech
|
|
||||||
}
|
|
||||||
|
|
||||||
play_queue.shuffle()
|
|
||||||
track_details = play_queue.get_next_track()
|
|
||||||
return controller.start_playback('play', speech, card, track_details, handler_input)
|
|
||||||
|
|
||||||
class NaviSonicPlayMusicByCurrentAlbum(AbstractRequestHandler):
|
|
||||||
"""Handle NaviSonicPlayMusicByCurrentAlbum Intent
|
|
||||||
|
|
||||||
Plays more music of the current playing Album
|
|
||||||
"""
|
|
||||||
|
|
||||||
def can_handle(self, handler_input: HandlerInput) -> bool:
|
|
||||||
return is_intent_name('NaviSonicPlayMusicByCurrentAlbum')(handler_input)
|
|
||||||
|
|
||||||
def handle(self, handler_input: HandlerInput) -> Response:
|
|
||||||
global backgroundProcess
|
|
||||||
logger.debug('In NaviSonicPlayMusicByCurrentAlbum Handler (custom)')
|
|
||||||
if backgroundProcess is not None:
|
|
||||||
backgroundProcess.terminate()
|
|
||||||
backgroundProcess.join()
|
|
||||||
|
|
||||||
t = get_current_song_details() #current "T"rack
|
|
||||||
|
|
||||||
artist_lookup = connection.search_artist(t["artist"])
|
|
||||||
artist_album_lookup = connection.albums_by_artist(artist_lookup[0].get('id'))
|
|
||||||
result = [album_result for album_result in artist_album_lookup if album_result.get('name').lower() == t["album"].lower()]
|
|
||||||
|
|
||||||
song_id_list = connection.build_song_list_from_albums(result, -1)
|
|
||||||
play_queue.clear()
|
|
||||||
|
|
||||||
controller.enqueue_songs(connection, play_queue, [song_id_list[0], song_id_list[1]]) # When generating the playlist return the first two tracks.
|
|
||||||
backgroundProcess = Process(target=queue_worker_thread, args=(connection, play_queue, song_id_list[2:])) # Create a thread to enqueue the remaining tracks
|
|
||||||
backgroundProcess.start() # Start the additional thread
|
|
||||||
|
|
||||||
speech = sanitise_speech_output(f'Tocando mais músicas do album {t["album"]}, de {t["artist"]}')
|
|
||||||
logger.info(speech)
|
|
||||||
|
|
||||||
card = {'title': 'AskNavidrome',
|
|
||||||
'text': speech
|
|
||||||
}
|
|
||||||
|
|
||||||
play_queue.shuffle()
|
|
||||||
track_details = play_queue.get_next_track()
|
|
||||||
return controller.start_playback('play', speech, card, track_details, handler_input)
|
|
||||||
|
|
||||||
class NaviSonicPlayAlbumByArtist(AbstractRequestHandler):
|
class NaviSonicPlayAlbumByArtist(AbstractRequestHandler):
|
||||||
"""Handle NaviSonicPlayAlbumByArtist
|
"""Handle NaviSonicPlayAlbumByArtist
|
||||||
@@ -464,8 +371,7 @@ class NaviSonicPlayAlbumByArtist(AbstractRequestHandler):
|
|||||||
artist_lookup = connection.search_artist(artist.value)
|
artist_lookup = connection.search_artist(artist.value)
|
||||||
|
|
||||||
if artist_lookup is None:
|
if artist_lookup is None:
|
||||||
#text = sanitise_speech_output(f"I couldn't find the artist {artist.value} in the collection.")
|
text = sanitise_speech_output(f"I couldn't find the artist {artist.value} in the collection.")
|
||||||
text = sanitise_speech_output(f"Não achei o artista {artist.value} na nossa coleção.")
|
|
||||||
handler_input.response_builder.speak(text).ask(text)
|
handler_input.response_builder.speak(text).ask(text)
|
||||||
|
|
||||||
return handler_input.response_builder.response
|
return handler_input.response_builder.response
|
||||||
@@ -478,8 +384,7 @@ class NaviSonicPlayAlbumByArtist(AbstractRequestHandler):
|
|||||||
result = [album_result for album_result in artist_album_lookup if album_result.get('name').lower() == album.value.lower()]
|
result = [album_result for album_result in artist_album_lookup if album_result.get('name').lower() == album.value.lower()]
|
||||||
|
|
||||||
if not result:
|
if not result:
|
||||||
#text = sanitise_speech_output(f"I couldn't find an album called {album.value} by {artist.value} in the collection.")
|
text = sanitise_speech_output(f"I couldn't find an album called {album.value} by {artist.value} in the collection.")
|
||||||
text = sanitise_speech_output(f"Não achei na nossa coleção um disco chamado {album.value} de {artist.value}.")
|
|
||||||
handler_input.response_builder.speak(text).ask(text)
|
handler_input.response_builder.speak(text).ask(text)
|
||||||
|
|
||||||
return handler_input.response_builder.response
|
return handler_input.response_builder.response
|
||||||
@@ -493,8 +398,7 @@ class NaviSonicPlayAlbumByArtist(AbstractRequestHandler):
|
|||||||
backgroundProcess = Process(target=queue_worker_thread, args=(connection, play_queue, song_id_list[2:])) # Create a thread to enqueue the remaining tracks
|
backgroundProcess = Process(target=queue_worker_thread, args=(connection, play_queue, song_id_list[2:])) # Create a thread to enqueue the remaining tracks
|
||||||
backgroundProcess.start() # Start the additional thread
|
backgroundProcess.start() # Start the additional thread
|
||||||
|
|
||||||
#speech = sanitise_speech_output(f'Playing {album.value} by: {artist.value}')
|
speech = sanitise_speech_output(f'Playing {album.value} by: {artist.value}')
|
||||||
speech = sanitise_speech_output(f'Tocando o álbum {album.value} de: {artist.value}')
|
|
||||||
logger.info(speech)
|
logger.info(speech)
|
||||||
card = {'title': 'AskNavidrome',
|
card = {'title': 'AskNavidrome',
|
||||||
'text': speech
|
'text': speech
|
||||||
@@ -510,8 +414,7 @@ class NaviSonicPlayAlbumByArtist(AbstractRequestHandler):
|
|||||||
result = connection.search_album(album.value)
|
result = connection.search_album(album.value)
|
||||||
|
|
||||||
if result is None:
|
if result is None:
|
||||||
#text = sanitise_speech_output(f"I couldn't find the album {album.value} in the collection.")
|
text = sanitise_speech_output(f"I couldn't find the album {album.value} in the collection.")
|
||||||
text = sanitise_speech_output(f"Não achei o disco {album.value} na nossa coleção.")
|
|
||||||
handler_input.response_builder.speak(text).ask(text)
|
handler_input.response_builder.speak(text).ask(text)
|
||||||
|
|
||||||
return handler_input.response_builder.response
|
return handler_input.response_builder.response
|
||||||
@@ -525,7 +428,7 @@ class NaviSonicPlayAlbumByArtist(AbstractRequestHandler):
|
|||||||
backgroundProcess = Process(target=queue_worker_thread, args=(connection, play_queue, song_id_list[2:])) # Create a thread to enqueue the remaining tracks
|
backgroundProcess = Process(target=queue_worker_thread, args=(connection, play_queue, song_id_list[2:])) # Create a thread to enqueue the remaining tracks
|
||||||
backgroundProcess.start() # Start the additional thread
|
backgroundProcess.start() # Start the additional thread
|
||||||
|
|
||||||
speech = sanitise_speech_output(f'Tocando o disco {album.value}')
|
speech = sanitise_speech_output(f'Playing {album.value}')
|
||||||
logger.info(speech)
|
logger.info(speech)
|
||||||
card = {'title': 'AskNavidrome',
|
card = {'title': 'AskNavidrome',
|
||||||
'text': speech
|
'text': speech
|
||||||
@@ -558,8 +461,7 @@ class NaviSonicPlaySongByArtist(AbstractRequestHandler):
|
|||||||
artist_lookup = connection.search_artist(artist.value)
|
artist_lookup = connection.search_artist(artist.value)
|
||||||
|
|
||||||
if artist_lookup is None:
|
if artist_lookup is None:
|
||||||
#text = sanitise_speech_output(f"I couldn't find the artist {artist.value} in the collection.")
|
text = sanitise_speech_output(f"I couldn't find the artist {artist.value} in the collection.")
|
||||||
text = sanitise_speech_output(f"Não achei o artista {artist.value} na nossa coleção.")
|
|
||||||
handler_input.response_builder.speak(text).ask(text)
|
handler_input.response_builder.speak(text).ask(text)
|
||||||
|
|
||||||
return handler_input.response_builder.response
|
return handler_input.response_builder.response
|
||||||
@@ -574,8 +476,7 @@ class NaviSonicPlaySongByArtist(AbstractRequestHandler):
|
|||||||
song_dets = [item.get('id') for item in song_list if item.get('artistId') == artist_id]
|
song_dets = [item.get('id') for item in song_list if item.get('artistId') == artist_id]
|
||||||
|
|
||||||
if not song_dets:
|
if not song_dets:
|
||||||
#text = sanitise_speech_output(f"I couldn't find a song called {song.value} by {artist.value} in the collection.")
|
text = sanitise_speech_output(f"I couldn't find a song called {song.value} by {artist.value} in the collection.")
|
||||||
text = sanitise_speech_output(f"Não achei uma música chamada {song.value} de {artist.value} na nossa coleção.")
|
|
||||||
handler_input.response_builder.speak(text).ask(text)
|
handler_input.response_builder.speak(text).ask(text)
|
||||||
|
|
||||||
return handler_input.response_builder.response
|
return handler_input.response_builder.response
|
||||||
@@ -583,7 +484,7 @@ class NaviSonicPlaySongByArtist(AbstractRequestHandler):
|
|||||||
play_queue.clear()
|
play_queue.clear()
|
||||||
controller.enqueue_songs(connection, play_queue, song_dets)
|
controller.enqueue_songs(connection, play_queue, song_dets)
|
||||||
|
|
||||||
speech = sanitise_speech_output(f'Tocando {song.value} de {artist.value}')
|
speech = sanitise_speech_output(f'Playing {song.value} by {artist.value}')
|
||||||
logger.info(speech)
|
logger.info(speech)
|
||||||
card = {'title': 'AskNavidrome',
|
card = {'title': 'AskNavidrome',
|
||||||
'text': speech
|
'text': speech
|
||||||
@@ -619,7 +520,7 @@ class NaviSonicPlayPlaylist(AbstractRequestHandler):
|
|||||||
playlist_id = connection.search_playlist(playlist.value)
|
playlist_id = connection.search_playlist(playlist.value)
|
||||||
|
|
||||||
if playlist_id is None:
|
if playlist_id is None:
|
||||||
text = sanitise_speech_output("Não achei a playlist " + str(playlist.value) + ' na nossa coleção.')
|
text = sanitise_speech_output("I couldn't find the playlist " + str(playlist.value) + ' in the collection.')
|
||||||
handler_input.response_builder.speak(text).ask(text)
|
handler_input.response_builder.speak(text).ask(text)
|
||||||
|
|
||||||
return handler_input.response_builder.response
|
return handler_input.response_builder.response
|
||||||
@@ -633,7 +534,7 @@ class NaviSonicPlayPlaylist(AbstractRequestHandler):
|
|||||||
backgroundProcess = Process(target=queue_worker_thread, args=(connection, play_queue, song_id_list[2:])) # Create a thread to enqueue the remaining tracks
|
backgroundProcess = Process(target=queue_worker_thread, args=(connection, play_queue, song_id_list[2:])) # Create a thread to enqueue the remaining tracks
|
||||||
backgroundProcess.start() # Start the additional thread
|
backgroundProcess.start() # Start the additional thread
|
||||||
|
|
||||||
speech = sanitise_speech_output('Tocando a playlist ' + str(playlist.value))
|
speech = sanitise_speech_output('Playing playlist ' + str(playlist.value))
|
||||||
logger.info(speech)
|
logger.info(speech)
|
||||||
card = {'title': 'AskNavidrome',
|
card = {'title': 'AskNavidrome',
|
||||||
'text': speech
|
'text': speech
|
||||||
@@ -668,7 +569,7 @@ class NaviSonicPlayMusicByGenre(AbstractRequestHandler):
|
|||||||
song_id_list = connection.build_song_list_from_genre(genre.value, min_song_count)
|
song_id_list = connection.build_song_list_from_genre(genre.value, min_song_count)
|
||||||
|
|
||||||
if song_id_list is None:
|
if song_id_list is None:
|
||||||
text = sanitise_speech_output(f"Não achei nada do estilo {genre.value} na nossa coleção.")
|
text = sanitise_speech_output(f"I couldn't find any {genre.value} songs in the collection.")
|
||||||
handler_input.response_builder.speak(text).ask(text)
|
handler_input.response_builder.speak(text).ask(text)
|
||||||
|
|
||||||
return handler_input.response_builder.response
|
return handler_input.response_builder.response
|
||||||
@@ -682,7 +583,7 @@ class NaviSonicPlayMusicByGenre(AbstractRequestHandler):
|
|||||||
backgroundProcess = Process(target=queue_worker_thread, args=(connection, play_queue, song_id_list[2:])) # Create a thread to enqueue the remaining tracks
|
backgroundProcess = Process(target=queue_worker_thread, args=(connection, play_queue, song_id_list[2:])) # Create a thread to enqueue the remaining tracks
|
||||||
backgroundProcess.start() # Start the additional thread
|
backgroundProcess.start() # Start the additional thread
|
||||||
|
|
||||||
speech = sanitise_speech_output(f'Tocando músicas do estilo {genre.value}')
|
speech = sanitise_speech_output(f'Playing {genre.value} music')
|
||||||
logger.info(speech)
|
logger.info(speech)
|
||||||
card = {'title': 'AskNavidrome',
|
card = {'title': 'AskNavidrome',
|
||||||
'text': speech
|
'text': speech
|
||||||
@@ -714,8 +615,7 @@ class NaviSonicPlayMusicRandom(AbstractRequestHandler):
|
|||||||
song_id_list = connection.build_random_song_list(min_song_count)
|
song_id_list = connection.build_random_song_list(min_song_count)
|
||||||
|
|
||||||
if song_id_list is None:
|
if song_id_list is None:
|
||||||
#text = sanitise_speech_output("I couldn't find any songs in the collection.")
|
text = sanitise_speech_output("I couldn't find any songs in the collection.")
|
||||||
text = sanitise_speech_output("Não achei nenhuma música na nossa coleção. Estranho.")
|
|
||||||
handler_input.response_builder.speak(text).ask(text)
|
handler_input.response_builder.speak(text).ask(text)
|
||||||
|
|
||||||
return handler_input.response_builder.response
|
return handler_input.response_builder.response
|
||||||
@@ -729,7 +629,7 @@ class NaviSonicPlayMusicRandom(AbstractRequestHandler):
|
|||||||
backgroundProcess = Process(target=queue_worker_thread, args=(connection, play_queue, song_id_list[2:])) # Create a thread to enqueue the remaining tracks
|
backgroundProcess = Process(target=queue_worker_thread, args=(connection, play_queue, song_id_list[2:])) # Create a thread to enqueue the remaining tracks
|
||||||
backgroundProcess.start() # Start the additional thread
|
backgroundProcess.start() # Start the additional thread
|
||||||
|
|
||||||
speech = sanitise_speech_output('Tocando qualquer coisa aleatória')
|
speech = sanitise_speech_output('Playing random music')
|
||||||
logger.info(speech)
|
logger.info(speech)
|
||||||
card = {'title': 'AskNavidrome',
|
card = {'title': 'AskNavidrome',
|
||||||
'text': speech
|
'text': speech
|
||||||
@@ -761,7 +661,7 @@ class NaviSonicPlayFavouriteSongs(AbstractRequestHandler):
|
|||||||
song_id_list = connection.build_song_list_from_favourites()
|
song_id_list = connection.build_song_list_from_favourites()
|
||||||
|
|
||||||
if song_id_list is None:
|
if song_id_list is None:
|
||||||
text = sanitise_speech_output("Não tenho nada nos favoritos.")
|
text = sanitise_speech_output("You don't have any favourite songs in the collection.")
|
||||||
handler_input.response_builder.speak(text).ask(text)
|
handler_input.response_builder.speak(text).ask(text)
|
||||||
|
|
||||||
return handler_input.response_builder.response
|
return handler_input.response_builder.response
|
||||||
@@ -775,7 +675,7 @@ class NaviSonicPlayFavouriteSongs(AbstractRequestHandler):
|
|||||||
backgroundProcess = Process(target=queue_worker_thread, args=(connection, play_queue, song_id_list[2:])) # Create a thread to enqueue the remaining tracks
|
backgroundProcess = Process(target=queue_worker_thread, args=(connection, play_queue, song_id_list[2:])) # Create a thread to enqueue the remaining tracks
|
||||||
backgroundProcess.start() # Start the additional thread
|
backgroundProcess.start() # Start the additional thread
|
||||||
|
|
||||||
speech = sanitise_speech_output('Tocando suas músicas favoritas.')
|
speech = sanitise_speech_output('Playing your favourite tracks.')
|
||||||
logger.info(speech)
|
logger.info(speech)
|
||||||
card = {'title': 'AskNavidrome',
|
card = {'title': 'AskNavidrome',
|
||||||
'text': speech
|
'text': speech
|
||||||
@@ -821,8 +721,7 @@ class NaviSonicSongDetails(AbstractRequestHandler):
|
|||||||
artist = sanitise_speech_output(current_track.artist)
|
artist = sanitise_speech_output(current_track.artist)
|
||||||
album = sanitise_speech_output(current_track.album)
|
album = sanitise_speech_output(current_track.album)
|
||||||
|
|
||||||
# text = f'This is {title} by {artist}, from the album {album}'
|
text = f'This is {title} by {artist}, from the album {album}'
|
||||||
text = f'Essa é {title} de {artist}, do album {album}'
|
|
||||||
handler_input.response_builder.speak(text)
|
handler_input.response_builder.speak(text)
|
||||||
|
|
||||||
return handler_input.response_builder.response
|
return handler_input.response_builder.response
|
||||||
@@ -1004,7 +903,8 @@ class NextPlaybackHandler(AbstractRequestHandler):
|
|||||||
"""Handle NextIntent"""
|
"""Handle NextIntent"""
|
||||||
|
|
||||||
def can_handle(self, handler_input: HandlerInput) -> bool:
|
def can_handle(self, handler_input: HandlerInput) -> bool:
|
||||||
return is_intent_name('AMAZON.NextIntent')(handler_input)
|
return (is_intent_name('AMAZON.NextIntent')(handler_input) or
|
||||||
|
is_request_type('PlaybackController.NextCommandIssued')(handler_input))
|
||||||
|
|
||||||
def handle(self, handler_input: HandlerInput) -> Response:
|
def handle(self, handler_input: HandlerInput) -> Response:
|
||||||
logger.debug('In NextPlaybackHandler')
|
logger.debug('In NextPlaybackHandler')
|
||||||
@@ -1021,7 +921,8 @@ class PreviousPlaybackHandler(AbstractRequestHandler):
|
|||||||
"""Handle PreviousIntent"""
|
"""Handle PreviousIntent"""
|
||||||
|
|
||||||
def can_handle(self, handler_input: HandlerInput) -> bool:
|
def can_handle(self, handler_input: HandlerInput) -> bool:
|
||||||
return is_intent_name('AMAZON.PreviousIntent')(handler_input)
|
return (is_intent_name('AMAZON.PreviousIntent')(handler_input) or
|
||||||
|
is_request_type('PlaybackController.PreviousCommandIssued')(handler_input))
|
||||||
|
|
||||||
def handle(self, handler_input: HandlerInput) -> Response:
|
def handle(self, handler_input: HandlerInput) -> Response:
|
||||||
logger.debug('In PreviousPlaybackHandler')
|
logger.debug('In PreviousPlaybackHandler')
|
||||||
@@ -1088,8 +989,7 @@ class SystemExceptionHandler(AbstractExceptionHandler):
|
|||||||
if get_request_type(handler_input) == 'IntentRequest':
|
if get_request_type(handler_input) == 'IntentRequest':
|
||||||
logger.error(f'Intent Name Was: {get_intent_name(handler_input)}')
|
logger.error(f'Intent Name Was: {get_intent_name(handler_input)}')
|
||||||
|
|
||||||
#speech = sanitise_speech_output("Sorry, I didn't get that. Can you please say it again!!")
|
speech = sanitise_speech_output("Sorry, I didn't get that. Can you please say it again!!")
|
||||||
speech = sanitise_speech_output("Foi mal, não entendi.")
|
|
||||||
handler_input.response_builder.speak(speech).ask(speech)
|
handler_input.response_builder.speak(speech).ask(speech)
|
||||||
|
|
||||||
return handler_input.response_builder.response
|
return handler_input.response_builder.response
|
||||||
@@ -1115,8 +1015,7 @@ class GeneralExceptionHandler(AbstractExceptionHandler):
|
|||||||
if get_request_type(handler_input) == 'IntentRequest':
|
if get_request_type(handler_input) == 'IntentRequest':
|
||||||
logger.error(f'Intent Name Was: {get_intent_name(handler_input)}')
|
logger.error(f'Intent Name Was: {get_intent_name(handler_input)}')
|
||||||
|
|
||||||
#speech = sanitise_speech_output("Sorry, I didn't get that. Can you please say it again!!")
|
speech = sanitise_speech_output("Sorry, I didn't get that. Can you please say it again!!")
|
||||||
speech = sanitise_speech_output("Foi mal, não entendi. Pode repetir!!")
|
|
||||||
handler_input.response_builder.speak(speech).ask(speech)
|
handler_input.response_builder.speak(speech).ask(speech)
|
||||||
|
|
||||||
return handler_input.response_builder.response
|
return handler_input.response_builder.response
|
||||||
@@ -1215,8 +1114,6 @@ sb.add_request_handler(NaviSonicPlayPlaylist())
|
|||||||
sb.add_request_handler(NaviSonicPlayFavouriteSongs())
|
sb.add_request_handler(NaviSonicPlayFavouriteSongs())
|
||||||
sb.add_request_handler(NaviSonicPlayMusicByGenre())
|
sb.add_request_handler(NaviSonicPlayMusicByGenre())
|
||||||
sb.add_request_handler(NaviSonicPlayMusicRandom())
|
sb.add_request_handler(NaviSonicPlayMusicRandom())
|
||||||
sb.add_request_handler(NaviSonicPlayMusicByCurrentArtist())
|
|
||||||
sb.add_request_handler(NaviSonicPlayMusicByCurrentAlbum())
|
|
||||||
sb.add_request_handler(NaviSonicRandomiseQueue())
|
sb.add_request_handler(NaviSonicRandomiseQueue())
|
||||||
sb.add_request_handler(NaviSonicSongDetails())
|
sb.add_request_handler(NaviSonicSongDetails())
|
||||||
sb.add_request_handler(NaviSonicStarSong())
|
sb.add_request_handler(NaviSonicStarSong())
|
||||||
|
|||||||
Regular → Executable
+15
-3
@@ -42,7 +42,19 @@ def start_playback(mode: str, text: str, card_data: dict, track_details: Track,
|
|||||||
:return: Amazon Alexa Response class
|
:return: Amazon Alexa Response class
|
||||||
:rtype: Response
|
:rtype: Response
|
||||||
"""
|
"""
|
||||||
|
metadata = AudioItemMetadata(
|
||||||
|
title=track_details.title,
|
||||||
|
subtitle=track_details.artist,
|
||||||
|
art=display.Image(
|
||||||
|
content_description=track_details.title,
|
||||||
|
sources=[
|
||||||
|
display.ImageInstance(
|
||||||
|
url='https://github.com/navidrome/navidrome/raw/master/resources/logo-192x192.png'
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if mode == 'play':
|
if mode == 'play':
|
||||||
# Starting playback
|
# Starting playback
|
||||||
logger.debug('In start_playback() - play mode')
|
logger.debug('In start_playback() - play mode')
|
||||||
@@ -67,7 +79,7 @@ def start_playback(mode: str, text: str, card_data: dict, track_details: Track,
|
|||||||
url=track_details.uri,
|
url=track_details.uri,
|
||||||
offset_in_milliseconds=track_details.offset,
|
offset_in_milliseconds=track_details.offset,
|
||||||
expected_previous_token=None),
|
expected_previous_token=None),
|
||||||
metadata=add_screen_background(card_data) if card_data else None
|
metadata=metadata
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
).set_should_end_session(True)
|
).set_should_end_session(True)
|
||||||
@@ -95,7 +107,7 @@ def start_playback(mode: str, text: str, card_data: dict, track_details: Track,
|
|||||||
# if the Previous intent is used
|
# if the Previous intent is used
|
||||||
offset_in_milliseconds=0,
|
offset_in_milliseconds=0,
|
||||||
expected_previous_token=track_details.previous_id),
|
expected_previous_token=track_details.previous_id),
|
||||||
metadata=None
|
metadata=metadata
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
).set_should_end_session(True)
|
).set_should_end_session(True)
|
||||||
|
|||||||
@@ -40,29 +40,41 @@ class SubsonicConnection:
|
|||||||
self.api_version,
|
self.api_version,
|
||||||
False)
|
False)
|
||||||
|
|
||||||
self.logger.debug('Connected to Navidrome')
|
self.logger.debug('Connecting to Navidrome.....')
|
||||||
|
|
||||||
def ping(self) -> bool:
|
def ping(self) -> bool:
|
||||||
"""Ping a Subsonic API server
|
"""Ping a Subsonic API server
|
||||||
|
|
||||||
Verify the connection to a Subsonic compatible API server
|
Verify the connection to a Subsonic compatible API server
|
||||||
is working
|
is working. Enhanced logging has been added to examine the
|
||||||
|
HTTP response returned from the server to assist with troubleshooting
|
||||||
|
connection issues.
|
||||||
|
|
||||||
:return: True if the connection works, False if it does not
|
:return: True if the connection works, False if it does not
|
||||||
:rtype: bool
|
:rtype: bool
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.logger.debug('In function ping()')
|
self.logger.debug('In function ping()')
|
||||||
status = self.conn.ping()
|
http_request = self.conn._getRequest('ping.view')
|
||||||
|
try:
|
||||||
|
http_request_result = self.conn._doInfoReq(http_request)
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error('Failed to connect to Navidrome: %s', e, exc_info=True)
|
||||||
|
return False
|
||||||
|
|
||||||
if status:
|
self.logger.debug('ping() response from server: %s', http_request_result)
|
||||||
# Success
|
status = http_request_result.get('status')
|
||||||
|
if status == 'ok':
|
||||||
self.logger.info('Successfully connected to Navidrome')
|
self.logger.info('Successfully connected to Navidrome')
|
||||||
|
return True
|
||||||
|
elif status == 'failed':
|
||||||
|
err = http_request_result.get('error', {})
|
||||||
|
self.logger.error('Failed to connect to Navidrome: code=%s msg=%s',
|
||||||
|
err.get('code'), err.get('message'))
|
||||||
|
return False
|
||||||
else:
|
else:
|
||||||
# Fail
|
self.logger.error('Unexpected error when connecting to Navidrome: %r', status)
|
||||||
self.logger.error('Failed to connect to Navidrome')
|
return False
|
||||||
|
|
||||||
return self.conn.ping()
|
|
||||||
|
|
||||||
def scrobble(self, track_id: str, time: int) -> None:
|
def scrobble(self, track_id: str, time: int) -> None:
|
||||||
"""Scrobble the given track
|
"""Scrobble the given track
|
||||||
|
|||||||
Reference in New Issue
Block a user