diff --git a/_migrations/2022-02-13-223514_twitch_event_rules/up.sql b/_migrations/2022-02-13-223514_twitch_event_rules/up.sql index 8860b62d1b..fa49582ef0 100644 --- a/_migrations/2022-02-13-223514_twitch_event_rules/up.sql +++ b/_migrations/2022-02-13-223514_twitch_event_rules/up.sql @@ -8,6 +8,10 @@ CREATE TABLE twitch_event_rules( -- Not used for anything except replication. id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + -- Idempotency token from client + -- This is so the frontend client doesn't submit duplicate jobs. + uuid_idempotency_token VARCHAR(36) NOT NULL, + -- Effective "primary key" (PUBLIC) token VARCHAR(32) NOT NULL, @@ -57,6 +61,7 @@ CREATE TABLE twitch_event_rules( -- INDICES -- PRIMARY KEY (id), + UNIQUE KEY (uuid_idempotency_token), UNIQUE KEY (token), KEY fk_user_token (user_token), KEY index_event_category (event_category), diff --git a/_migrations/2022-02-16-072149_api_tokens/up.sql b/_migrations/2022-02-16-072149_api_tokens/up.sql index 08b7bb2698..900dc7239b 100644 --- a/_migrations/2022-02-16-072149_api_tokens/up.sql +++ b/_migrations/2022-02-16-072149_api_tokens/up.sql @@ -32,8 +32,8 @@ CREATE TABLE api_tokens ( -- INDICES -- PRIMARY KEY (id), - UNIQUE KEY (api_token), UNIQUE KEY (uuid_idempotency_token), + UNIQUE KEY (api_token), KEY fk_user_token (user_token), KEY index_created_at (created_at), KEY index_deleted_at (deleted_at) diff --git a/crates/lib/database_queries/src/column_types/mod.rs b/crates/lib/database_queries/src/column_types/mod.rs index 1c108ef9c1..6ecfe45966 100644 --- a/crates/lib/database_queries/src/column_types/mod.rs +++ b/crates/lib/database_queries/src/column_types/mod.rs @@ -1,3 +1,4 @@ pub mod job_status; pub mod record_visibility; -pub mod vocoder_type; \ No newline at end of file +pub mod twitch_event_category; +pub mod vocoder_type; diff --git a/crates/lib/database_queries/src/column_types/twitch_event_category.rs b/crates/lib/database_queries/src/column_types/twitch_event_category.rs new file mode 100644 index 0000000000..269b5d9ccf --- /dev/null +++ b/crates/lib/database_queries/src/column_types/twitch_event_category.rs @@ -0,0 +1,35 @@ +//! These are columns where users can control the visibility of their data. + +use anyhow::anyhow; +use container_common::anyhow_result::AnyhowResult; + +/// To use this in a query, the query must have type annotations. +/// See: https://www.gitmemory.com/issue/launchbadge/sqlx/1241/847154375 +/// eg. twitch_event_category as `twitch_event_category: crate::column_types::twitch_event_category::TwitchEventCategory` +#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize, sqlx::Type)] +#[serde(rename_all = "snake_case")] +#[sqlx(rename_all = "snake_case")] +pub enum TwitchEventCategory { + Bits, + ChannelPoints, + ChatCommand, +} + +impl TwitchEventCategory { + pub fn to_str(&self) -> &'static str { + match self { + Self::Bits => "bits", + Self::ChannelPoints => "channel_points", + Self::ChatCommand => "chat_command", + } + } + + pub fn from_str(value: &str) -> AnyhowResult { + match value { + "bits" => Ok(Self::Bits), + "channel_points" => Ok(Self::ChannelPoints), + "chat_command" => Ok(Self::ChatCommand), + _ => Err(anyhow!("invalid value: {:?}", value)), + } + } +} diff --git a/crates/lib/database_queries/src/lib.rs b/crates/lib/database_queries/src/lib.rs index 57b7a39eda..90c1d15440 100644 --- a/crates/lib/database_queries/src/lib.rs +++ b/crates/lib/database_queries/src/lib.rs @@ -7,5 +7,6 @@ pub mod column_types; pub mod helpers; pub mod tokens; pub mod tts; +pub mod twitch_event_rules; pub mod twitch_oauth; pub mod twitch_pubsub; diff --git a/crates/lib/database_queries/src/tokens.rs b/crates/lib/database_queries/src/tokens.rs index 8d1b9e9336..eebb15f7fe 100644 --- a/crates/lib/database_queries/src/tokens.rs +++ b/crates/lib/database_queries/src/tokens.rs @@ -66,4 +66,10 @@ impl Tokens { pub fn new_twitch_oauth_grouping_token() -> AnyhowResult { random_prefix_crockford_token("OG:", 32, false) } + + // ========== [Twitch] Tokens not typically visible to users ========== + + pub fn new_twitch_event_rule() -> AnyhowResult { + random_prefix_crockford_token("TER:", 32, false) + } } diff --git a/crates/lib/database_queries/src/twitch_event_rules/create_event_rule.rs b/crates/lib/database_queries/src/twitch_event_rules/create_event_rule.rs new file mode 100644 index 0000000000..6eae6d8685 --- /dev/null +++ b/crates/lib/database_queries/src/twitch_event_rules/create_event_rule.rs @@ -0,0 +1,61 @@ +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 TwitchEventRuleInsertBuilder { + pub uuid_idempotency_token: String, + pub user_token: String, + pub event_category: TwitchEventCategory, + pub event_match_predicate: String, + pub event_response: String, + pub user_specified_rule_order: u32, + pub rule_is_enabled: bool, + pub ip_address_creation: String, +} + +impl TwitchEventRuleInsertBuilder { + + /// Returns the newly generated token. + pub async fn insert(&self, mysql_pool: &MySqlPool) -> AnyhowResult { + + let token = Tokens::new_twitch_event_rule()?; + + let query = sqlx::query!( + r#" +INSERT INTO twitch_event_rules +SET + uuid_idempotency_token = ?, + token = ?, + user_token = ?, + event_category = ?, + event_match_predicate = ?, + event_response = ?, + user_specified_rule_order = ?, + rule_is_enabled = ?, + ip_address_creation = ?, + ip_address_last_update = ? + "#, + &self.uuid_idempotency_token, + &token, + &self.user_token, + &self.event_category, + &self.event_match_predicate, + &self.event_response, + &self.user_specified_rule_order, + &self.rule_is_enabled, + &self.ip_address_creation, + &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 Twitch Event Rule: {:?}", err)), + }; + + Ok(token) + } +} diff --git a/crates/lib/database_queries/src/twitch_event_rules/mod.rs b/crates/lib/database_queries/src/twitch_event_rules/mod.rs new file mode 100644 index 0000000000..690e3110f8 --- /dev/null +++ b/crates/lib/database_queries/src/twitch_event_rules/mod.rs @@ -0,0 +1 @@ +pub mod create_event_rule; \ No newline at end of file diff --git a/crates/service/storyteller_web/src/http_server/endpoints/twitch/event_rules/create_event_rule.rs b/crates/service/storyteller_web/src/http_server/endpoints/twitch/event_rules/create_event_rule.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/crates/service/storyteller_web/src/http_server/endpoints/twitch/event_rules/delete_event_rule.rs b/crates/service/storyteller_web/src/http_server/endpoints/twitch/event_rules/delete_event_rule.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/crates/service/storyteller_web/src/http_server/endpoints/twitch/event_rules/edit_event_rule.rs b/crates/service/storyteller_web/src/http_server/endpoints/twitch/event_rules/edit_event_rule.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/crates/service/storyteller_web/src/http_server/endpoints/twitch/event_rules/list_event_rules_for_user.rs b/crates/service/storyteller_web/src/http_server/endpoints/twitch/event_rules/list_event_rules_for_user.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/crates/service/storyteller_web/src/http_server/endpoints/twitch/event_rules/mod.rs b/crates/service/storyteller_web/src/http_server/endpoints/twitch/event_rules/mod.rs new file mode 100644 index 0000000000..4f40936c19 --- /dev/null +++ b/crates/service/storyteller_web/src/http_server/endpoints/twitch/event_rules/mod.rs @@ -0,0 +1,4 @@ +pub mod create_event_rule; +pub mod delete_event_rule; +pub mod edit_event_rule; +pub mod list_event_rules_for_user; \ No newline at end of file diff --git a/crates/service/storyteller_web/src/http_server/endpoints/twitch/mod.rs b/crates/service/storyteller_web/src/http_server/endpoints/twitch/mod.rs index 0b47d3ca95..1d15747836 100644 --- a/crates/service/storyteller_web/src/http_server/endpoints/twitch/mod.rs +++ b/crates/service/storyteller_web/src/http_server/endpoints/twitch/mod.rs @@ -1,3 +1,4 @@ +pub mod event_rules; pub mod oauth_begin_json; pub mod oauth_begin_redirect; pub mod oauth_end;