add database
All checks were successful
tests / fmt (push) Successful in 1m46s
tests / clippy (push) Successful in 1m48s
tests / test (push) Successful in 1m50s
tests / pre-commit (push) Successful in 2m5s
tests / build (push) Successful in 2m31s
deploy / release-image (push) Successful in 5m44s
All checks were successful
tests / fmt (push) Successful in 1m46s
tests / clippy (push) Successful in 1m48s
tests / test (push) Successful in 1m50s
tests / pre-commit (push) Successful in 2m5s
tests / build (push) Successful in 2m31s
deploy / release-image (push) Successful in 5m44s
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use crate::colors;
|
||||
use crate::commands::join::join_channel;
|
||||
use crate::metadata::{Metadata, MetadataMap};
|
||||
use crate::state::State;
|
||||
use crate::{colors, db};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use songbird::input::{Compose, YoutubeDl};
|
||||
@@ -180,12 +180,51 @@ pub(crate) async fn play(
|
||||
.clone()
|
||||
.or(yttrack.url.clone())
|
||||
.ok_or("Could not find url")?;
|
||||
|
||||
let mut src = YoutubeDl::new(reqwest::Client::new(), url.clone());
|
||||
let src_copy = src.clone();
|
||||
let track: Track = src_copy.into();
|
||||
|
||||
if let Ok(metadata) = src.aux_metadata().await {
|
||||
debug!("metadata: {:?}", metadata);
|
||||
|
||||
let (author_name, author_global_name) = if let Some(author) = interaction.author() {
|
||||
(author.name.clone(), author.global_name.clone())
|
||||
} else {
|
||||
("".to_string(), None)
|
||||
};
|
||||
|
||||
db::track::insert_guild(&state.pool, db::track::Guild::new(guild_id.to_string()))
|
||||
.await
|
||||
.expect("failed to insert guild: {e}");
|
||||
|
||||
db::track::insert_user(
|
||||
&state.pool,
|
||||
db::track::User::new(user_id.to_string(), author_name, author_global_name),
|
||||
)
|
||||
.await
|
||||
.expect("failed to insert user: {e}");
|
||||
|
||||
let track_id = db::track::insert_track(
|
||||
&state.pool,
|
||||
db::track::Track::new(
|
||||
url.clone(),
|
||||
yttrack.title.clone(),
|
||||
yttrack.channel.clone(),
|
||||
yttrack.duration_string.clone(),
|
||||
metadata.thumbnail.clone().unwrap_or_default(),
|
||||
),
|
||||
)
|
||||
.await
|
||||
.expect("failed to insert track: {e}");
|
||||
|
||||
db::track::insert_query(
|
||||
&state.pool,
|
||||
db::track::Query::new(user_id.to_string(), guild_id.to_string(), track_id),
|
||||
)
|
||||
.await
|
||||
.expect("failed to insert track: {e}");
|
||||
|
||||
tracks_added.push(TrackType {
|
||||
url: url.clone(),
|
||||
title: metadata.title.clone(),
|
||||
|
||||
1
src/db/mod.rs
Normal file
1
src/db/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod track;
|
||||
146
src/db/track.rs
Normal file
146
src/db/track.rs
Normal file
@@ -0,0 +1,146 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use sqlx::FromRow;
|
||||
|
||||
#[derive(Debug, FromRow)]
|
||||
pub(crate) struct Track {
|
||||
#[allow(dead_code)]
|
||||
pub(crate) id: i64,
|
||||
pub(crate) url: String,
|
||||
pub(crate) title: String,
|
||||
pub(crate) channel: String,
|
||||
pub(crate) duration: String,
|
||||
pub(crate) thumbnail: String,
|
||||
pub(crate) updated: DateTime<Utc>,
|
||||
}
|
||||
impl Track {
|
||||
pub(crate) fn new(
|
||||
url: String,
|
||||
title: String,
|
||||
channel: String,
|
||||
duration: String,
|
||||
thumbnail: String,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: 0,
|
||||
url,
|
||||
title,
|
||||
channel,
|
||||
duration,
|
||||
thumbnail,
|
||||
updated: chrono::offset::Utc::now(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn insert_track(
|
||||
pool: &sqlx::SqlitePool,
|
||||
track: Track,
|
||||
) -> Result<i64, sqlx::Error> {
|
||||
let query =
|
||||
"INSERT OR REPLACE INTO tracks (url, title, channel, duration, thumbnail, updated) VALUES ($1, $2, $3, $4, $5, $6)";
|
||||
let res = sqlx::query(query)
|
||||
.bind(track.url)
|
||||
.bind(track.title)
|
||||
.bind(track.channel)
|
||||
.bind(track.duration)
|
||||
.bind(track.thumbnail)
|
||||
.bind(track.updated)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
Ok(res.last_insert_rowid())
|
||||
}
|
||||
|
||||
#[derive(Debug, FromRow)]
|
||||
pub(crate) struct User {
|
||||
pub(crate) id: String,
|
||||
pub(crate) name: String,
|
||||
pub(crate) global_name: Option<String>,
|
||||
pub(crate) updated: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl User {
|
||||
pub(crate) fn new(id: String, name: String, global_name: Option<String>) -> Self {
|
||||
Self {
|
||||
id,
|
||||
name,
|
||||
global_name,
|
||||
updated: chrono::offset::Utc::now(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn insert_user(pool: &sqlx::SqlitePool, user: User) -> Result<(), sqlx::Error> {
|
||||
let query =
|
||||
"INSERT OR REPLACE INTO users (id, name, global_name, updated) VALUES ($1, $2, $3, $4)";
|
||||
sqlx::query(query)
|
||||
.bind(user.id)
|
||||
.bind(user.name)
|
||||
.bind(user.global_name)
|
||||
.bind(user.updated)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Debug, FromRow)]
|
||||
pub(crate) struct Query {
|
||||
#[allow(dead_code)]
|
||||
pub(crate) id: i64,
|
||||
pub(crate) user_id: String,
|
||||
pub(crate) guild_id: String,
|
||||
pub(crate) track_id: i64,
|
||||
pub(crate) updated: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl Query {
|
||||
pub(crate) fn new(user_id: String, guild_id: String, track_id: i64) -> Self {
|
||||
Self {
|
||||
id: 0,
|
||||
user_id,
|
||||
guild_id,
|
||||
track_id,
|
||||
updated: chrono::offset::Utc::now(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn insert_query(pool: &sqlx::SqlitePool, q: Query) -> Result<i64, sqlx::Error> {
|
||||
let query =
|
||||
"INSERT OR REPLACE INTO queries (user_id, guild_id, track_id, updated) VALUES ($1, $2, $3, $4)";
|
||||
let res = sqlx::query(query)
|
||||
.bind(q.user_id)
|
||||
.bind(q.guild_id)
|
||||
.bind(q.track_id)
|
||||
.bind(q.updated)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
Ok(res.last_insert_rowid())
|
||||
}
|
||||
|
||||
#[derive(Debug, FromRow)]
|
||||
pub(crate) struct Guild {
|
||||
pub(crate) id: String,
|
||||
pub(crate) updated: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl Guild {
|
||||
pub(crate) fn new(id: String) -> Self {
|
||||
Self {
|
||||
id,
|
||||
updated: chrono::offset::Utc::now(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn insert_guild(
|
||||
pool: &sqlx::SqlitePool,
|
||||
guild: Guild,
|
||||
) -> Result<i64, sqlx::Error> {
|
||||
let query = "INSERT OR REPLACE INTO guilds (id, updated) VALUES ($1, $2)";
|
||||
let res = sqlx::query(query)
|
||||
.bind(guild.id)
|
||||
.bind(guild.updated)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
Ok(res.last_insert_rowid())
|
||||
}
|
||||
13
src/main.rs
13
src/main.rs
@@ -1,7 +1,9 @@
|
||||
mod handler;
|
||||
use handler::Handler;
|
||||
use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions};
|
||||
mod colors;
|
||||
mod commands;
|
||||
mod db;
|
||||
mod interaction_commands;
|
||||
mod metadata;
|
||||
mod signal;
|
||||
@@ -38,6 +40,16 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
|
||||
info!("Starting up...");
|
||||
|
||||
let (mut shards, state) = {
|
||||
let db = env::var("DATABASE_URL").map_err(|_| "DATABASE_URL is not set")?;
|
||||
let options = SqliteConnectOptions::new()
|
||||
.create_if_missing(true)
|
||||
.filename(&db);
|
||||
let pool = SqlitePoolOptions::new()
|
||||
.max_connections(5)
|
||||
.connect_with(options)
|
||||
.await?;
|
||||
sqlx::migrate!().run(&pool).await?;
|
||||
|
||||
let token = env::var("DISCORD_TOKEN").map_err(|_| "DISCORD_TOKEN is not set")?;
|
||||
let app_id = env::var("DISCORD_APP_ID")
|
||||
.map_err(|_| "DISCORD_APP_ID is not set")?
|
||||
@@ -80,6 +92,7 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
|
||||
songbird,
|
||||
standby: Standby::new(),
|
||||
guild_settings: Default::default(),
|
||||
pool,
|
||||
}),
|
||||
)
|
||||
};
|
||||
|
||||
@@ -32,4 +32,5 @@ pub(crate) struct StateRef {
|
||||
pub(crate) songbird: Songbird,
|
||||
pub(crate) standby: Standby,
|
||||
pub(crate) guild_settings: DashMap<Id<GuildMarker>, Settings>,
|
||||
pub(crate) pool: sqlx::SqlitePool,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user