Add database to store spotify-youtube mappings
When playing a single youtube song the equivalent song will be searched on spotify and stored in the database. The assumption is that a user prefers studio versions of songs from youtube which are harder to search for automatically. Signed-off-by: trivernis <trivernis@protonmail.com>pull/14/head
parent
a733e6a2ac
commit
c8ab28e4e4
@ -0,0 +1,2 @@
|
||||
-- This file should undo anything in `up.sql`
|
||||
DROP TABLE youtube_songs;
|
@ -0,0 +1,11 @@
|
||||
-- Your SQL goes here
|
||||
CREATE TABLE youtube_songs (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
spotify_id VARCHAR(255) NOT NULL,
|
||||
artist VARCHAR(128) NOT NULL,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
album VARCHAR(255) NOT NULL,
|
||||
url VARCHAR(128) NOT NULL,
|
||||
score INTEGER DEFAULT 0 NOT NULL,
|
||||
UNIQUE (spotify_id, url)
|
||||
)
|
@ -0,0 +1,60 @@
|
||||
use diesel::insert_into;
|
||||
use diesel::prelude::*;
|
||||
use tokio_diesel::*;
|
||||
|
||||
use crate::error::DatabaseResult;
|
||||
use crate::models::*;
|
||||
use crate::schema::*;
|
||||
use crate::Database;
|
||||
|
||||
impl Database {
|
||||
/// Adds a song to the database or increments the score when it
|
||||
/// already exists
|
||||
pub async fn add_song(
|
||||
&self,
|
||||
spotify_id: &str,
|
||||
artist: &str,
|
||||
title: &str,
|
||||
album: &str,
|
||||
url: &str,
|
||||
) -> DatabaseResult<()> {
|
||||
use youtube_songs::dsl;
|
||||
log::debug!(
|
||||
"Inserting/Updating song in database spotify_id: '{}' artist: '{}', title: '{}', album: '{}', url: '{}'",
|
||||
spotify_id,
|
||||
artist,
|
||||
title,
|
||||
album,
|
||||
url,
|
||||
);
|
||||
|
||||
insert_into(dsl::youtube_songs)
|
||||
.values(YoutubeSongInsert {
|
||||
spotify_id: spotify_id.to_string(),
|
||||
artist: artist.to_string(),
|
||||
title: title.to_string(),
|
||||
album: album.to_string(),
|
||||
url: url.to_string(),
|
||||
})
|
||||
.on_conflict((dsl::spotify_id, dsl::url))
|
||||
.do_update()
|
||||
.set(dsl::score.eq(dsl::score + 1))
|
||||
.execute_async(&self.pool)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns the song with the best score for the given query
|
||||
pub async fn get_song(&self, spotify_id: &str) -> DatabaseResult<Option<YoutubeSong>> {
|
||||
use youtube_songs::dsl;
|
||||
let songs: Vec<YoutubeSong> = dsl::youtube_songs
|
||||
.filter(dsl::spotify_id.eq(spotify_id))
|
||||
.order(dsl::score.desc())
|
||||
.limit(1)
|
||||
.load_async::<YoutubeSong>(&self.pool)
|
||||
.await?;
|
||||
|
||||
Ok(songs.into_iter().next())
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue