From 71e8da44bfcf557d40033e5fd47f8bc4b9b8dcea Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Fri, 18 Feb 2022 20:47:56 -0500 Subject: [PATCH] queries for voice clone request insert / fetch --- .../up.sql | 4 + crates/lib/database_queries/src/lib.rs | 1 + crates/lib/database_queries/src/tokens.rs | 4 + .../get_voice_clone_request.rs | 162 ++++++++++++++++++ .../insert_voice_clone_requests_builder.rs | 122 +++++++++++++ .../src/voice_clone_requests/mod.rs | 2 + 6 files changed, 295 insertions(+) create mode 100644 crates/lib/database_queries/src/voice_clone_requests/get_voice_clone_request.rs create mode 100644 crates/lib/database_queries/src/voice_clone_requests/insert_voice_clone_requests_builder.rs create mode 100644 crates/lib/database_queries/src/voice_clone_requests/mod.rs diff --git a/_migrations/2022-02-19-004032_voice_clone_requests/up.sql b/_migrations/2022-02-19-004032_voice_clone_requests/up.sql index 9db197dbd7..a1435d7d44 100644 --- a/_migrations/2022-02-19-004032_voice_clone_requests/up.sql +++ b/_migrations/2022-02-19-004032_voice_clone_requests/up.sql @@ -38,6 +38,10 @@ CREATE TABLE voice_clone_requests( is_for_private_use BOOLEAN NOT NULL DEFAULT FALSE, is_for_public_use BOOLEAN NOT NULL DEFAULT FALSE, + -- Ownership + is_own_voice BOOLEAN NOT NULL DEFAULT FALSE, + is_third_party_voice BOOLEAN NOT NULL DEFAULT FALSE, + -- ========== RECORDING QUALITY / EQUIPMENT ========== has_clean_audio_recordings BOOLEAN NOT NULL DEFAULT FALSE, diff --git a/crates/lib/database_queries/src/lib.rs b/crates/lib/database_queries/src/lib.rs index 90c1d15440..a248fcebb1 100644 --- a/crates/lib/database_queries/src/lib.rs +++ b/crates/lib/database_queries/src/lib.rs @@ -10,3 +10,4 @@ pub mod tts; pub mod twitch_event_rules; pub mod twitch_oauth; pub mod twitch_pubsub; +pub mod voice_clone_requests; diff --git a/crates/lib/database_queries/src/tokens.rs b/crates/lib/database_queries/src/tokens.rs index 48ecf16b99..20fb8abef8 100644 --- a/crates/lib/database_queries/src/tokens.rs +++ b/crates/lib/database_queries/src/tokens.rs @@ -59,6 +59,10 @@ impl Tokens { random_prefix_crockford_token("EV:", 32, false) } + pub fn new_voice_clone_request_token() -> AnyhowResult { + random_prefix_crockford_token("VCR:", 32, false) + } + pub fn new_category() -> AnyhowResult { random_prefix_crockford_token("CAT:", 15, false) } diff --git a/crates/lib/database_queries/src/voice_clone_requests/get_voice_clone_request.rs b/crates/lib/database_queries/src/voice_clone_requests/get_voice_clone_request.rs new file mode 100644 index 0000000000..390532cc90 --- /dev/null +++ b/crates/lib/database_queries/src/voice_clone_requests/get_voice_clone_request.rs @@ -0,0 +1,162 @@ +use anyhow::anyhow; +use chrono::{Utc, DateTime}; +use container_common::anyhow_result::AnyhowResult; +use crate::column_types::twitch_event_category::TwitchEventCategory; +use crate::helpers::boolean_converters::i8_to_bool; +use sqlx::MySqlPool; + +/// Used for both *BY TOKEN* and for *BY USER* lookups. +/// The user field should be optional for one and not for the other, but code reuse is more +/// important and this is a quick / hasty feature. +#[derive(Debug)] +pub struct VoiceCloneRequest { + pub token: String, + + // Contact + pub maybe_user_token: Option, + pub email_address: String, + pub discord_username: String, + + // Use + pub is_for_studio: bool, + pub is_for_twitch_tts: bool, + pub is_for_api_use: bool, + pub is_for_music: bool, + pub is_for_games: bool, + pub is_for_other: bool, + pub optional_notes_on_use: Option, + + // Visibility + pub is_for_private_use: bool, + pub is_for_public_use: bool, + + // Ownership + pub is_own_voice: bool, + pub is_third_party_voice: bool, + + // Equipment + pub has_clean_audio_recordings: bool, + pub has_good_microphone: bool, + + // Comments + pub optional_questions: Option, + pub optional_extra_comments: Option, + + pub created_at: chrono::DateTime, + pub updated_at: chrono::DateTime, +} + +pub async fn get_voice_clone_request_by_token( + voice_clone_request_token: &str, + pool: &MySqlPool, +) -> AnyhowResult> { + + let maybe_record = sqlx::query_as!( + VoiceCloneRequestInternal, + r#" +SELECT + token, + + maybe_user_token, + email_address, + discord_username, + + is_for_studio, + is_for_twitch_tts, + is_for_api_use, + is_for_music, + is_for_games, + is_for_other, + optional_notes_on_use, + + is_for_private_use, + is_for_public_use, + + is_own_voice, + is_third_party_voice, + + has_clean_audio_recordings, + has_good_microphone, + + optional_questions, + optional_extra_comments, + + created_at, + updated_at +FROM voice_clone_requests +WHERE + token = ? + "#, + voice_clone_request_token, + ) + .fetch_one(pool) + .await; + + let record : VoiceCloneRequestInternal = match maybe_record { + Ok(record) => record, + Err(sqlx::Error::RowNotFound) => return Ok(None), + Err(ref err) => return Err(anyhow!("database query error: {:?}", err)), + }; + + Ok(Some(VoiceCloneRequest { + token: record.token, + maybe_user_token: record.maybe_user_token, + email_address: record.email_address, + discord_username: record.discord_username, + is_for_studio: i8_to_bool(record.is_for_studio), + is_for_twitch_tts: i8_to_bool(record.is_for_twitch_tts), + is_for_api_use: i8_to_bool(record.is_for_api_use), + is_for_music: i8_to_bool(record.is_for_music), + is_for_games: i8_to_bool(record.is_for_games), + is_for_other: i8_to_bool(record.is_for_other), + optional_notes_on_use: record.optional_notes_on_use, + is_for_private_use: i8_to_bool(record.is_for_private_use), + is_for_public_use: i8_to_bool(record.is_for_public_use), + is_own_voice: i8_to_bool(record.is_own_voice), + is_third_party_voice: i8_to_bool(record.is_third_party_voice), + has_clean_audio_recordings: i8_to_bool(record.has_clean_audio_recordings), + has_good_microphone: i8_to_bool(record.has_good_microphone), + optional_questions: record.optional_questions, + optional_extra_comments: record.optional_extra_comments, + created_at: record.created_at, + updated_at: record.updated_at, + })) +} + +#[derive(Debug)] +struct VoiceCloneRequestInternal { + pub token: String, + + // Contact + pub maybe_user_token: Option, + pub email_address: String, + pub discord_username: String, + + // Use + pub is_for_studio: i8, + pub is_for_twitch_tts: i8, + pub is_for_api_use: i8, + pub is_for_music: i8, + pub is_for_games: i8, + pub is_for_other: i8, + pub optional_notes_on_use: Option, + + // Visibility + pub is_for_private_use: i8, + pub is_for_public_use: i8, + + // Ownership + pub is_own_voice: i8, + pub is_third_party_voice: i8, + + // Equipment + pub has_clean_audio_recordings: i8, + pub has_good_microphone: i8, + + // Comments + pub optional_questions: Option, + pub optional_extra_comments: Option, + + pub created_at: chrono::DateTime, + pub updated_at: chrono::DateTime, +} diff --git a/crates/lib/database_queries/src/voice_clone_requests/insert_voice_clone_requests_builder.rs b/crates/lib/database_queries/src/voice_clone_requests/insert_voice_clone_requests_builder.rs new file mode 100644 index 0000000000..59c2052369 --- /dev/null +++ b/crates/lib/database_queries/src/voice_clone_requests/insert_voice_clone_requests_builder.rs @@ -0,0 +1,122 @@ +use anyhow::anyhow; +use container_common::anyhow_result::AnyhowResult; +use crate::column_types::twitch_event_category::TwitchEventCategory; +use crate::tokens::Tokens; +use sqlx::MySqlPool; + +pub struct InsertVoiceCloneRequestBuilder { + pub uuid_idempotency_token: String, + + // Contact + pub maybe_user_token: Option, + pub email_address: String, + pub discord_username: String, + + // Use + pub is_for_studio: bool, + pub is_for_twitch_tts: bool, + pub is_for_api_use: bool, + pub is_for_music: bool, + pub is_for_games: bool, + pub is_for_other: bool, + pub optional_notes_on_use: Option, + + // Visibility + pub is_for_private_use: bool, + pub is_for_public_use: bool, + + // Ownership + pub is_own_voice: bool, + pub is_third_party_voice: bool, + + // Equipment + pub has_clean_audio_recordings: bool, + pub has_good_microphone: bool, + + // Comments + pub optional_questions: Option, + pub optional_extra_comments: Option, + + pub ip_address_creation: String, +} + +impl InsertVoiceCloneRequestBuilder { + + /// Returns the newly generated token. + pub async fn insert(&self, mysql_pool: &MySqlPool) -> AnyhowResult { + + let token = Tokens::new_voice_clone_request_token()?; + + let query = sqlx::query!( + r#" +INSERT INTO voice_clone_requests +SET + token = ?, + uuid_idempotency_token = ?, + + maybe_user_token = ?, + email_address = ?, + discord_username = ?, + + is_for_studio = ?, + is_for_twitch_tts = ?, + is_for_api_use = ?, + is_for_music = ?, + is_for_games = ?, + is_for_other = ?, + optional_notes_on_use = ?, + + is_for_private_use = ?, + is_for_public_use = ?, + + is_own_voice = ?, + is_third_party_voice = ?, + + has_clean_audio_recordings = ?, + has_good_microphone = ?, + + optional_questions = ?, + optional_extra_comments = ?, + + ip_address_creation = ? + "#, + &token, + &self.uuid_idempotency_token, + + &self.maybe_user_token, + &self.email_address, + &self.discord_username, + + &self.is_for_studio, + &self.is_for_twitch_tts, + &self.is_for_api_use, + &self.is_for_music, + &self.is_for_games, + &self.is_for_other, + &self.optional_notes_on_use, + + &self.is_for_private_use, + &self.is_for_public_use, + + &self.is_own_voice, + &self.is_third_party_voice, + + &self.has_clean_audio_recordings, + &self.has_good_microphone, + + &self.optional_questions, + &self.optional_extra_comments, + + &self.ip_address_creation, + ); + + let query_result = query.execute(mysql_pool).await; + + let _record_id = match query_result { + Ok(res) => res.last_insert_id(), + Err(err) => return Err(anyhow!("Error creating Voice Clone Request: {:?}", err)), + }; + + Ok(token) + } +} diff --git a/crates/lib/database_queries/src/voice_clone_requests/mod.rs b/crates/lib/database_queries/src/voice_clone_requests/mod.rs new file mode 100644 index 0000000000..cd31493d36 --- /dev/null +++ b/crates/lib/database_queries/src/voice_clone_requests/mod.rs @@ -0,0 +1,2 @@ +pub mod get_voice_clone_request; +pub mod insert_voice_clone_requests_builder; \ No newline at end of file