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
trivernis 3 years ago
parent a733e6a2ac
commit c8ab28e4e4
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

@ -23,6 +23,20 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "bot-database"
version = "0.4.0"
dependencies = [
"chrono",
"diesel",
"diesel_migrations",
"dotenv",
"log",
"r2d2",
"thiserror",
"tokio-diesel",
]
[[package]]
name = "byteorder"
version = "1.4.3"
@ -48,20 +62,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "database"
version = "0.1.0"
dependencies = [
"chrono",
"diesel",
"diesel_migrations",
"dotenv",
"log",
"r2d2",
"thiserror",
"tokio-diesel",
]
[[package]]
name = "diesel"
version = "1.4.6"

@ -1,6 +1,6 @@
[package]
name = "bot-database"
version = "0.3.0"
version = "0.4.0"
authors = ["trivernis <trivernis@protonmail.com>"]
edition = "2018"

@ -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)
)

@ -2,6 +2,7 @@ pub use gifs::*;
pub use guild_playlists::*;
pub use guild_playlists::*;
pub use statistics::*;
pub use youtube_songs::*;
use crate::PoolConnection;
@ -9,6 +10,7 @@ mod gifs;
mod guild_playlists;
mod guild_settings;
mod statistics;
mod youtube_songs;
#[derive(Clone)]
pub struct Database {

@ -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())
}
}

@ -56,3 +56,24 @@ pub struct StatisticInsert {
pub success: bool,
pub error_msg: Option<String>,
}
#[derive(Queryable, Debug, Clone)]
pub struct YoutubeSong {
pub id: i64,
pub spotify_id: String,
pub artist: String,
pub title: String,
pub album: String,
pub url: String,
pub score: i32,
}
#[derive(Insertable, Debug)]
#[table_name = "youtube_songs"]
pub struct YoutubeSongInsert {
pub spotify_id: String,
pub artist: String,
pub title: String,
pub album: String,
pub url: String,
}

@ -34,9 +34,22 @@ table! {
}
}
table! {
youtube_songs (id) {
id -> Int8,
spotify_id -> Varchar,
artist -> Varchar,
title -> Varchar,
album -> Varchar,
url -> Varchar,
score -> Int4,
}
}
allow_tables_to_appear_in_same_query!(
gifs,
guild_playlists,
guild_settings,
statistics,
youtube_songs,
);

Loading…
Cancel
Save