1 Commits

Author SHA1 Message Date
7edd14c628 save tracks
All checks were successful
tests / fmt (push) Successful in 48s
tests / clippy (push) Successful in 1m14s
tests / pre-commit (push) Successful in 1m21s
tests / test (push) Successful in 1m32s
tests / build (push) Successful in 1m48s
deploy / release-image (push) Successful in 4m45s
2024-06-27 22:45:09 +02:00
5 changed files with 75 additions and 11 deletions

View File

@@ -1,4 +1,3 @@
-- Add migration script here
CREATE TABLE IF NOT EXISTS tracks
(
id INTEGER PRIMARY KEY AUTOINCREMENT,

View File

@@ -0,0 +1,5 @@
CREATE TABLE IF NOT EXISTS blobs
(
id INTEGER PRIMARY KEY AUTOINCREMENT,
data BLOB
);

View File

@@ -1,14 +1,18 @@
use crate::commands::join::join_channel;
use crate::db::track::{insert_blob, Blob};
use crate::metadata::{Metadata, MetadataMap};
use crate::state::State;
use crate::state::{State, StateRef};
use crate::{colors, db};
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use songbird::input::cached::Memory;
use songbird::input::{Compose, YoutubeDl};
use songbird::tracks::Track;
use std::io::{BufRead, BufReader};
use songbird::{Event, EventContext, EventHandler, TrackEvent};
use std::io::{BufRead, BufReader, Read};
use std::ops::Sub;
use std::sync::Arc;
use std::{error::Error, time::Duration};
use tokio::process::Command;
use tracing::debug;
@@ -183,10 +187,8 @@ pub(crate) async fn play(
.ok_or("Could not find url")?;
let mut src = YoutubeDl::new(reqwest::Client::new(), url.clone());
let src_copy = src.clone();
let src_copy2 = src.clone();
let _m = Memory::new(src_copy2.into());
let track: Track = src_copy.into();
let memory = Memory::new(src.clone().into()).await.unwrap();
let track: Track = memory.new_handle().into();
if let Ok(metadata) = src.aux_metadata().await {
debug!("metadata: {:?}", metadata);
@@ -255,6 +257,17 @@ pub(crate) async fn play(
url,
src,
});
handle
.add_event(
Event::Track(TrackEvent::Preparing),
TrackPreparingNotifier {
memory,
track_id,
state: Arc::clone(&state),
},
)
.expect("could not add event");
}
}
}
@@ -350,6 +363,31 @@ pub(crate) async fn play(
Ok(())
}
struct TrackPreparingNotifier {
memory: Memory,
track_id: i64,
state: Arc<StateRef>,
}
#[async_trait]
impl EventHandler for TrackPreparingNotifier {
async fn act(&self, _ctx: &EventContext<'_>) -> Option<Event> {
tracing::info!("Build buffer");
let mut reader = BufReader::new(self.memory.new_handle());
let mut bytes = Vec::new();
reader
.read_to_end(&mut bytes)
.expect("could not read track in memory");
tracing::info!("Saving track");
insert_blob(&self.state.pool, Blob::new(self.track_id, bytes))
.await
.expect("could not insert blob");
tracing::info!("Saved");
None
}
}
#[cfg(test)]
mod tests {
use super::*;

View File

@@ -144,3 +144,25 @@ pub(crate) async fn insert_guild(
.await?;
Ok(res.last_insert_rowid())
}
#[derive(Debug, FromRow)]
pub(crate) struct Blob {
pub(crate) id: i64,
pub(crate) data: Vec<u8>,
}
impl Blob {
pub(crate) fn new(id: i64, data: Vec<u8>) -> Self {
Self { id, data }
}
}
pub(crate) async fn insert_blob(pool: &sqlx::SqlitePool, blob: Blob) -> Result<(), sqlx::Error> {
let query = "INSERT OR REPLACE INTO blobs (id, data) VALUES ($1, $2)";
sqlx::query(query)
.bind(blob.id)
.bind(blob.data)
.execute(pool)
.await?;
Ok(())
}

View File

@@ -16,7 +16,7 @@ use futures::StreamExt;
use signal::signal_handler;
use songbird::{shards::TwilightMap, Songbird};
use state::StateRef;
use std::{env, error::Error, sync::Arc};
use std::{env, error::Error, str::FromStr, sync::Arc};
use tokio::select;
use tracing::{debug, info};
use twilight_cache_inmemory::InMemoryCache;
@@ -41,9 +41,9 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
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 options = SqliteConnectOptions::from_str(&db)
.expect("could not create options")
.create_if_missing(true);
let pool = SqlitePoolOptions::new()
.max_connections(5)
.connect_with(options)