🎧 OpenTune 1.8.0
🚀 Mejoras y Novedades en OpenTune 1.8.0
- Inicio de sesión: sigue siendo necesario inicar sesion para evitar los errores de descargas:
- Mejora del diseño de Integracion con discord: Ahora funciona la integracion con discord (Rich) y se rediseño (Beta)
SELECT song.*
SELECT song.id, song.title, song.thumbnailUrl,
(SELECT COUNT(1)
FROM event
WHERE songId = song.id
AND timestamp > :fromTimeStamp AND timestamp <= :toTimeStamp) AS songCountListened,
(SELECT SUM(event.playTime)
FROM event
WHERE songId = song.id
AND timestamp > :fromTimeStamp AND timestamp <= :toTimeStamp) AS timeListened
FROM song
JOIN (SELECT songId
FROM event
WHERE timestamp > :fromTimeStamp
AND timestamp <= :toTimeStamp
GROUP BY songId
ORDER BY SUM(playTime) DESC
LIMIT :limit)
ON song.id = songId
LIMIT :limit
OFFSET :offset
""",
)
fun mostPlayedSongsStats(
limit: Int = 6,
offset: Int = 0,
fromTimeStamp: Long,
toTimeStamp: Long? = LocalDateTime.now().toInstant(ZoneOffset.UTC).toEpochMilli(),
): Flow<List<SongWithStats>>
@Transaction
@Query(
"""
SELECT song.*,
(SELECT COUNT(1)
FROM event
WHERE songId = song.id
AND timestamp > :fromTimeStamp AND timestamp <= :toTimeStamp) AS songCountListened,
(SELECT SUM(event.playTime)
FROM event
WHERE songId = song.id
AND timestamp > :fromTimeStamp AND timestamp <= :toTimeStamp) AS timeListened
FROM song
JOIN (SELECT songId
FROM event
WHERE timestamp > :fromTimeStamp
AND timestamp <= :toTimeStamp
GROUP BY songId
ORDER BY SUM(playTime) DESC
LIMIT :limit)
@@ -328,6 +372,7 @@ interface DatabaseDao {
fromTimeStamp: Long,
limit: Int = 6,
offset: Int = 0,
toTimeStamp: Long? = LocalDateTime.now().toInstant(ZoneOffset.UTC).toEpochMilli(),
): Flow<List<Song>>
@Transaction
@@ -338,13 +383,19 @@ interface DatabaseDao {
FROM song_artist_map
JOIN event ON song_artist_map.songId = event.songId
WHERE artistId = artist.id
AND timestamp > :fromTimeStamp) AS songCount
AND timestamp > :fromTimeStamp AND timestamp <= :toTimeStamp) AS songCount,
(SELECT SUM(event.playTime)
FROM song_artist_map
JOIN event ON song_artist_map.songId = event.songId
WHERE artistId = artist.id
AND timestamp > :fromTimeStamp AND timestamp <= :toTimeStamp) AS timeListened
FROM artist
JOIN(SELECT artistId, SUM(songTotalPlayTime) AS totalPlayTime
FROM song_artist_map
JOIN (SELECT songId, SUM(playTime) AS songTotalPlayTime
FROM event
WHERE timestamp > :fromTimeStamp
AND timestamp <= :toTimeStamp
GROUP BY songId) AS e
ON song_artist_map.songId = e.songId
GROUP BY artistId
@@ -358,30 +409,42 @@ interface DatabaseDao {
fromTimeStamp: Long,
limit: Int = 6,
offset: Int = 0,
toTimeStamp: Long? = LocalDateTime.now().toInstant(ZoneOffset.UTC).toEpochMilli(),
): Flow<List<Artist>>
@Transaction
@Query(
"""
SELECT album.*
SELECT album.*,
(SELECT COUNT(1)
FROM song_album_map
JOIN event ON song_album_map.songId = event.songId
WHERE albumId = album.id
AND timestamp > :fromTimeStamp AND timestamp <= :toTimeStamp) AS songCountListened,
(SELECT SUM(event.playTime)
FROM song_album_map
JOIN event ON song_album_map.songId = event.songId
WHERE albumId = album.id
AND timestamp > :fromTimeStamp AND timestamp <= :toTimeStamp) AS timeListened
FROM album
JOIN(SELECT albumId
FROM song
JOIN (SELECT songId, SUM(playTime) AS songTotalPlayTime
FROM event
WHERE timestamp > :fromTimeStamp
GROUP BY songId) AS e
ON song.id = e.songId
WHERE albumId IS NOT NULL
GROUP BY albumId
ORDER BY SUM(songTotalPlayTime) DESC
LIMIT :limit)
ON album.id = albumId
WHERE id IN (SELECT song.albumId
FROM event
JOIN
song
ON event.songId = song.id
WHERE event.timestamp > :fromTimeStamp
AND event.timestamp <= :toTimeStamp
GROUP BY song.albumId
HAVING song.albumId IS NOT NULL)
ORDER BY timeListened DESC
LIMIT :limit OFFSET :offset
""",
)
fun mostPlayedAlbums(
fromTimeStamp: Long,
limit: Int = 6,
offset: Int = 0,
toTimeStamp: Long? = LocalDateTime.now().toInstant(ZoneOffset.UTC).toEpochMilli(),
): Flow<List<Album>>
@Transaction
@@ -773,6 +836,10 @@ interface DatabaseDao {
@Query("SELECT * FROM event ORDER BY rowId DESC")
fun events(): Flow<List<EventWithSong>>
@Transaction
@Query("SELECT * FROM event ORDER BY rowId ASC LIMIT 1")
fun firstEvent(): Flow<EventWithSong>
@Query("DELETE FROM event")
fun clearListenHistory()
@@ -900,7 +967,17 @@ interface DatabaseDao {
albumPage.songs
.map(SongItem::toMediaMetadata)
.onEach(::insert)
.mapIndexed { index, song ->
.onEach {
update(
it.toSongEntity().copy(
title = it.title,
duration = it.duration,
thumbnailUrl = it.thumbnailUrl,
albumId = it.album?.id,
albumName = it.album?.title,
),
)
}.mapIndexed { index, song ->
SongAlbumMap(
songId = song.id,
albumId = albumPage.album.browseId,
@@ -1006,7 +1083,17 @@ interface DatabaseDao {
albumPage.songs
.map(SongItem::toMediaMetadata)
.onEach(::insert)
.mapIndexed { index, song ->
.onEach {
update(
it.toSongEntity().copy(
title = it.title,
duration = it.duration,
thumbnailUrl = it.thumbnailUrl,
albumId = it.album?.id,
albumName = it.album?.title,
),
)
}.mapIndexed { index, song ->
SongAlbumMap(
songId = song.id,
albumId = albumPage.album.browseId,
@@ -1089,3 +1176,4 @@ interface DatabaseDao {
raw("PRAGMA wal_checkpoint(FULL)".toSQLiteQuery())
}
}
-
Corrección en el sistema de descargas: Hemos resuelto el problema que afectaba la descarga de contenido, garantizando una experiencia de usuario más fluida y confiable.
-
Control sobre contenido impulsado por IA: Los usuarios ahora pueden activar o desactivar el contenido generado por inteligencia artificial según sus preferencias personales.
-
Optimización de dependencias: Se corrigió un error en una de las librerías principales, mejorando la estabilidad y rendimiento general de la aplicación.
-
Integración con Discord: La integración con Discord ha sido mejorada, permitiendo compartir en tiempo real la música que estás escuchando. A continuación, un ejemplo de código para configurar la integración:
import com.discord.integration.DiscordRichPresence
import com.discord.integration.DiscordAPI
fun setupDiscordIntegration(trackName: String, artistName: String) {
val presence = DiscordRichPresence().apply {
details = "Escuchando: $trackName"
state = "Artista: $artistName"
largeImageKey = "opentune_icon"
largeImageText = "OpenTune 1.8.0"
startTimestamp = System.currentTimeMillis() / 1000
}
DiscordAPI.updatePresence(presence)
}
// Llama esta función al iniciar una canción
setupDiscordIntegration("Nombre de la canción", "Nombre del artista")
🔗 Contribuye al Proyecto
OpenTune es un proyecto de código abierto. Si deseas colaborar en su desarrollo o explorar el código fuente, no dudes en realizar un fork o enviar tus pull requests.
Registro Completo de Cambios: Comparar versiones