Exec Body Fn should be passed Parent BotAction #43

Merged
modulatingforce merged 19 commits from parent-botaction-to-child-fn into main 2024-03-25 16:29:44 -04:00

Original Title : Exec Body Fn should be passed Parent BotAction

Passing Parent BotAction to Child ExecBody functions would allow child functions to access attributes of the BotAction including :

  • Parent BotAction's Module
    • This would allow child functions to be able to do additional validation based on BotAction module if required . For example, when validating the module is enabled on a target channel

At the moment, an example use case I want this is for Chat.Say() to validate the target channel first

  • #TODO Implementing this may be it's own PR or if easy enough, I can tack it on here as a type of test

This is a small blocker of enhanced routine functionality , as Child ExecBodies may want to pull attributes from the Parent Routine . Routine core functionality can run without the changes from this PR


The change would require relatively major refactoring, I believe. In particular, I believe the following areas :

  • bot_actions.rs
// ...
  pub type ExecBody = Box<
        dyn Fn(BotAR, PrivmsgMessage) -> Pin<Box<dyn Future<Output = ()> + Send>> + Send + Sync,
    >;

    pub fn asyncbox<T>(f: fn(BotAR, PrivmsgMessage) -> T) -> ExecBody
    where
        T: Future<Output = ()> + Send + 'static,
    {
        Box::new(move |a, b| Box::pin(f(a, b)))
    }
// ...
  • Every Definition of BotAction such such as BotCommand or Listener

Plan of Action :

  • Code in new BotAction structure in above areas for desired functionality
  • QA Test & Validate
    • In particular, with adjustment to Chat.Say() so it validates Module of Target Channel
    • Live tests
  • Clippy / Format & Comments Cleanup
_Original Title : Exec Body Fn should be passed Parent BotAction_ Passing Parent `BotAction` to Child ExecBody functions would allow child functions to access attributes of the BotAction including : - Parent BotAction's Module - This would allow child functions to be able to do additional validation based on BotAction module if required . For example, when validating the module is enabled on a target channel At the moment, an example use case I want this is for `Chat.Say()` to validate the target channel first - [x] _#TODO_ Implementing this may be it's own PR *or* if easy enough, I can tack it on here as a type of test --- This is a small blocker of enhanced routine functionality , as Child ExecBodies may want to pull attributes from the Parent Routine . Routine core functionality can run without the changes from this PR --- The change would require relatively major refactoring, I believe. In particular, I believe the following areas : - `bot_actions.rs` ```rust // ... pub type ExecBody = Box< dyn Fn(BotAR, PrivmsgMessage) -> Pin<Box<dyn Future<Output = ()> + Send>> + Send + Sync, >; pub fn asyncbox<T>(f: fn(BotAR, PrivmsgMessage) -> T) -> ExecBody where T: Future<Output = ()> + Send + 'static, { Box::new(move |a, b| Box::pin(f(a, b))) } // ... ``` - Every Definition of BotAction such such as BotCommand or Listener --- # Plan of Action : - [x] Code in new `BotAction` structure in above areas for desired functionality - [x] QA Test & Validate - [x] In particular, with adjustment to `Chat.Say()` so it validates Module of Target Channel - [x] Live tests - [x] Clippy / Format & Comments Cleanup
modulatingforce self-assigned this 2024-03-24 11:28:56 -04:00
modulatingforce added this to the Rust Learning project 2024-03-24 11:28:58 -04:00
modulatingforce added the
Kind/Enhancement
Priority
Medium
labels 2024-03-24 11:29:59 -04:00
modulatingforce added 7 commits 2024-03-24 21:51:38 -04:00
modulatingforce added 5 commits 2024-03-24 23:44:26 -04:00
modulatingforce added 2 commits 2024-03-25 10:07:59 -04:00
notif BotMsgType
All checks were successful
ci/woodpecker/pr/cargo-checks Pipeline was successful
10d25bf34f
Author
Owner

BotMsgType:Notif takes care of some recursive loops I kept seeing with new Chat validation

  • I want to ensure though the following scenario is covered :
  1. If a BotAdmin without Channel Level Elevated Role (Mod,etc), they must promote themselves first in Both Source & Destination Channels
  2. Otherwise, if they say/sayinreplyto to a Channel without those roles, a send_botmsg of BotMsgType:Notif is sent in the Source Channel - this is also validated to ensure the user has elevated privileges (any) here too but slightly different handling (it will send a notif even if BotAdmin but other roles also)

At the moment, I'm able to do this (problem) scenario :

  1. In TestChannel, demote myself so I only have BotAdmin
  2. In my own (Broadcaster) channel, s TestChannel to send a message to the Destination Channel
  3. The message sends to the Destination Channel (ISSUE)
  4. (EXPECATION) The message should not have sent to Destination Channel & an Error Notification Should have been attempted on the Source Channel

Potential way to approach,
I should have a way so the roles are checked just in the destination if say message ?

`BotMsgType:Notif` takes care of some recursive loops I kept seeing with new `Chat` validation - [x] I want to ensure though the following scenario is covered : 1. If a `BotAdmin` without Channel Level Elevated Role (Mod,etc), they must promote themselves first in Both Source & Destination Channels 2. Otherwise, if they say/sayinreplyto to a Channel without those roles, a send_botmsg of BotMsgType:Notif is sent in the Source Channel - this is also validated to ensure the user has elevated privileges (any) here too but slightly different handling (it will send a notif even if BotAdmin but other roles also) At the moment, I'm able to do this (problem) scenario : 1. In TestChannel, demote myself so I only have BotAdmin 2. In my own (Broadcaster) channel, `s TestChannel` to send a message to the Destination Channel 3. The message sends to the Destination Channel (*ISSUE*) 4. (*EXPECATION*) The message should not have sent to Destination Channel & an Error Notification Should have been attempted on the Source Channel --- Potential way to approach, I should have a way so the roles are checked just in the destination if say message ?
Author
Owner

Live Tests - Passed

[x] Test Case > PASSED

Scenario

  • Sender has BotAdmin role
  • At Source Channel, Sender does NOT have any Channel_Elevated roles
  • At Destination Channel, Sender does NOT have any Channel_Elevated roles

Workflow

  1. Attempt Send Say to Destination
  2. Find the Sender does NOT have Channel_Elevated Roles for Desintation
  3. Send Notif to Source (by using PrivMsg)
  4. Find the Sender does NOT have Channel_Elevated Roles for Source
  5. Find the Sender does have BotAdmin Role
  6. Handle Notif by passing to Client.Say()

[x] Test Case > PASSED

Scenario

  • Sender has BotAdmin role
  • At Source Channel, Sender does have SOME Channel_Elevated roles
  • At Destination Channel, Sender does NOT have any Channel_Elevated roles

Workflow

  1. Attempt Send Say to Destination
  2. Find the Sender does NOT have Channel_Elevated Roles for Desintation
  3. Send Notif to Source (by using PrivMsg)
  4. Find the Sender does have SOME Channel_Elevated Roles for Source
  5. Handle Notif by passing to Client.Say()

[x] Test Case > PASSED

Scenario

  • Sender Does NOT have BotAdmin role
  • At Source Channel, Sender does NOT have any Channel_Elevated roles
  • At Destination Channel, Sender does NOT have any Channel_Elevated roles

Workflow

  1. Attempt Send Say to Destination
  2. Find the Sender does NOT have Channel_Elevated Roles for Desintation
  3. Send Notif to Source (by using PrivMsg)
  4. Find the Sender does NOT have Channel_Elevated Roles for Source
  5. Find the Sender does NOT have BotAdmin Role
  6. return without any Notif message sent

[x] Test Case > PASSED

Scenario

  • Sender Does NOT have BotAdmin role
  • At Source Channel, Sender does have SOME Channel_Elevated roles
  • At Destination Channel, Sender does NOT have any Channel_Elevated roles

Workflow

  1. Attempt Send Say to Destination
  2. Find the Sender does NOT have Channel_Elevated Roles for Desintation
  3. Send Notif to Source (by using PrivMsg)
  4. Find the Sender does have SOME Channel_Elevated Roles for Source
  5. Handle Notif by passing to Client.Say()

[x] Test Case > PASSED

Scenario

  • Sender has BotAdmin role
  • At Source Channel, Sender does NOT have any Channel_Elevated roles
  • At Destination Channel, Sender does have SOME Channel_Elevated roles

Workflow

  1. Attempt Send Say to Destination
  2. Find the Sender does have SOME Channel_Elevated Roles for Desintation
  3. Handle Say by passing to Client.Say()

[x] Test Case > PASSED

Scenario

  • Sender has BotAdmin role
  • At Source Channel, Sender does have SOME Channel_Elevated roles
  • At Destination Channel, Sender does have SOME Channel_Elevated roles

Workflow

  1. Attempt Send Say to Destination
  2. Find the Sender does have SOME Channel_Elevated Roles for Desintation
  3. Handle Say by passing to Client.Say()

[x] Test Case > PASSED

Scenario

  • Sender Does NOT have BotAdmin role
  • At Source Channel, Sender does NOT have any Channel_Elevated roles
  • At Destination Channel, Sender does have SOME Channel_Elevated roles

Workflow

  1. Attempt Send Say to Destination
  2. Find the Sender does have SOME Channel_Elevated Roles for Desintation
  3. Handle Say by passing to Client.Say()

[x] Test Case > PASSED

Scenario

  • Sender Does NOT have BotAdmin role
  • At Source Channel, Sender does have SOME Channel_Elevated roles
  • At Destination Channel, Sender does have SOME Channel_Elevated roles

Workflow

  1. Attempt Send Say to Destination
  2. Find the Sender does have SOME Channel_Elevated Roles for Desintation
  3. Handle Say by passing to Client.Say()
# Live Tests - Passed # [x] Test Case > PASSED Scenario - Sender has `BotAdmin` role - At `Source` Channel, Sender does NOT have any `Channel_Elevated` roles - At `Destination` Channel, Sender does NOT have any `Channel_Elevated` roles Workflow 1. Attempt Send `Say` to `Destination` 2. Find the Sender does NOT have `Channel_Elevated` Roles for `Desintation` 3. Send `Notif` to `Source` (by using `PrivMsg`) 4. Find the Sender does NOT have `Channel_Elevated` Roles for `Source` 5. Find the Sender does have `BotAdmin` Role 6. Handle `Notif` by passing to `Client.Say()` # [x] Test Case > PASSED Scenario - Sender has `BotAdmin` role - At `Source` Channel, Sender does have SOME `Channel_Elevated` roles - At `Destination` Channel, Sender does NOT have any `Channel_Elevated` roles Workflow 1. Attempt Send `Say` to `Destination` 2. Find the Sender does NOT have `Channel_Elevated` Roles for `Desintation` 3. Send `Notif` to `Source` (by using `PrivMsg`) 4. Find the Sender does have SOME `Channel_Elevated` Roles for `Source` 6. Handle `Notif` by passing to `Client.Say()` # [x] Test Case > PASSED Scenario - Sender Does NOT have `BotAdmin` role - At `Source` Channel, Sender does NOT have any `Channel_Elevated` roles - At `Destination` Channel, Sender does NOT have any `Channel_Elevated` roles Workflow 1. Attempt Send `Say` to `Destination` 2. Find the Sender does NOT have `Channel_Elevated` Roles for `Desintation` 3. Send `Notif` to `Source` (by using `PrivMsg`) 4. Find the Sender does NOT have `Channel_Elevated` Roles for `Source` 5. Find the Sender does NOT have `BotAdmin` Role 6. `return` without any `Notif` message sent # [x] Test Case > PASSED Scenario - Sender Does NOT have `BotAdmin` role - At `Source` Channel, Sender does have SOME `Channel_Elevated` roles - At `Destination` Channel, Sender does NOT have any `Channel_Elevated` roles Workflow 1. Attempt Send `Say` to `Destination` 2. Find the Sender does NOT have `Channel_Elevated` Roles for `Desintation` 3. Send `Notif` to `Source` (by using `PrivMsg`) 4. Find the Sender does have SOME `Channel_Elevated` Roles for `Source` 6. Handle `Notif` by passing to `Client.Say()` # [x] Test Case > PASSED Scenario - Sender has `BotAdmin` role - At `Source` Channel, Sender does NOT have any `Channel_Elevated` roles - At `Destination` Channel, Sender does have SOME `Channel_Elevated` roles Workflow 1. Attempt Send `Say` to `Destination` 2. Find the Sender does have SOME `Channel_Elevated` Roles for `Desintation` 3. Handle `Say` by passing to `Client.Say()` # [x] Test Case > PASSED Scenario - Sender has `BotAdmin` role - At `Source` Channel, Sender does have SOME `Channel_Elevated` roles - At `Destination` Channel, Sender does have SOME `Channel_Elevated` roles Workflow 1. Attempt Send `Say` to `Destination` 2. Find the Sender does have SOME `Channel_Elevated` Roles for `Desintation` 3. Handle `Say` by passing to `Client.Say()` # [x] Test Case > PASSED Scenario - Sender Does NOT have `BotAdmin` role - At `Source` Channel, Sender does NOT have any `Channel_Elevated` roles - At `Destination` Channel, Sender does have SOME `Channel_Elevated` roles Workflow 1. Attempt Send `Say` to `Destination` 2. Find the Sender does have SOME `Channel_Elevated` Roles for `Desintation` 3. Handle `Say` by passing to `Client.Say()` # [x] Test Case > PASSED Scenario - Sender Does NOT have `BotAdmin` role - At `Source` Channel, Sender does have SOME `Channel_Elevated` roles - At `Destination` Channel, Sender does have SOME `Channel_Elevated` roles Workflow 1. Attempt Send `Say` to `Destination` 2. Find the Sender does have SOME `Channel_Elevated` Roles for `Desintation` 3. Handle `Say` by passing to `Client.Say()`
Author
Owner

Business Logic : Chat Module's enum BotMsgType

#[derive(Clone,Debug)]
pub enum BotMsgType<'a> {
    SayInReplyTo(&'a PrivmsgMessage,String),
    Say(String,String),
    Notif(String), // For Bot Sent Notifications
}

impl Chat {
    pub fn init(
        ratelimiters: HashMap<Channel, RateLimiter>,
        client: TwitchIRCClient<TCPTransport<TLS>, StaticLoginCredentials>,
    ) -> Chat {
//...
}

    #[async_recursion]
    // async fn send_botmsg(&self, msginput: BotMsgType<'_>, params : ExecBodyParams) {
    pub async fn send_botmsg(&self, msginput: BotMsgType<'async_recursion>, params : ExecBodyParams) {

//...
}


    pub async fn say_in_reply_to(&self, msg: &PrivmsgMessage, outmsg: String , params : ExecBodyParams) {


    pub async fn say(&self, channel_login: String, message: String , params : ExecBodyParams) {



As a Custom or Core Developer, when Sending a Message, I should keep the following in mind

  • Send a BotMsgType::Notif to send_botmsg() if I want to ensure the Roles of the Sender in the Source Channel is Considered first before sending the Notification message to the Source Channel

    • These are generally for Core Features ; for example, when sending an error response - but only to elevated users like BotAdmin or Channel elevated users
  • Send a say() or say_in_reply_to() that's very similar to Client API , but includes passing an ExecBodyParams

    • These are handled primarily in Custom Features . For example, when sending a fun message to a different channel
    • these still go through the same process and access control validation as send_botmsg(), but raises a BotMsgType::Notif in certain scenarios of access control failures
# Business Logic : `Chat` Module's `enum BotMsgType` ```rust #[derive(Clone,Debug)] pub enum BotMsgType<'a> { SayInReplyTo(&'a PrivmsgMessage,String), Say(String,String), Notif(String), // For Bot Sent Notifications } impl Chat { pub fn init( ratelimiters: HashMap<Channel, RateLimiter>, client: TwitchIRCClient<TCPTransport<TLS>, StaticLoginCredentials>, ) -> Chat { //... } #[async_recursion] // async fn send_botmsg(&self, msginput: BotMsgType<'_>, params : ExecBodyParams) { pub async fn send_botmsg(&self, msginput: BotMsgType<'async_recursion>, params : ExecBodyParams) { //... } pub async fn say_in_reply_to(&self, msg: &PrivmsgMessage, outmsg: String , params : ExecBodyParams) { pub async fn say(&self, channel_login: String, message: String , params : ExecBodyParams) { ``` --- As a Custom or Core Developer, when Sending a Message, I should keep the following in mind - Send a `BotMsgType::Notif` to `send_botmsg()` if I want to ensure the Roles of the Sender in the Source Channel is Considered first before sending the Notification message to the Source Channel - These are generally for Core Features ; for example, when sending an error response - but only to elevated users like `BotAdmin` or Channel elevated users - Send a `say()` or `say_in_reply_to()` that's very _similar_ to `Client` API , but includes passing an `ExecBodyParams` - These are handled primarily in Custom Features . For example, when sending a fun message to a different channel - these still go through the same process and access control validation as `send_botmsg()`, but raises a `BotMsgType::Notif` in certain scenarios of access control failures
Author
Owner

Business Logic : bot_actions module's struct ExecBodyParams


pub type BotAR = Arc<RwLock<BotInstance>>;
pub type ActAR = Arc<RwLock<BotAction>>;


#[derive(Clone)]
pub struct ExecBodyParams {
    pub bot : BotAR,
    pub msg : PrivmsgMessage,
    pub parent_act : ActAR , 
}


impl ExecBodyParams {

    pub async fn get_parent_module(&self) -> Option<BotModule> {
}

    pub fn get_sender(&self) -> String {
}

    pub fn get_sender_chatbadge(&self) -> Option<ChatBadge> {
}


As a Custom or Core Developer, for BotActions , I could used passed params::ExecBodyParams to pull locks or data from common parameters such as the bot or parent BotAction

As a Core Developer , when developing features that require enhancing (adding or adjusting) passed input parameters to ExecBodies , we can just adjust this one area at struct definition, then adjust other areas if required (generally is not required when at least adding more members)

# Business Logic : `bot_actions` module's `struct ExecBodyParams` ```rust pub type BotAR = Arc<RwLock<BotInstance>>; pub type ActAR = Arc<RwLock<BotAction>>; #[derive(Clone)] pub struct ExecBodyParams { pub bot : BotAR, pub msg : PrivmsgMessage, pub parent_act : ActAR , } impl ExecBodyParams { pub async fn get_parent_module(&self) -> Option<BotModule> { } pub fn get_sender(&self) -> String { } pub fn get_sender_chatbadge(&self) -> Option<ChatBadge> { } ``` --- As a Custom or Core Developer, for `BotActions` , I could used passed `params::ExecBodyParams` to pull locks or data from common parameters such as the `bot` or parent `BotAction` As a Core Developer , when developing features that require enhancing (adding or adjusting) passed input parameters to ExecBodies , we can just adjust this one area at struct definition, then adjust other areas if required (generally is not required when at least adding more members)
modulatingforce added 3 commits 2024-03-25 15:26:15 -04:00
modulatingforce added 2 commits 2024-03-25 16:19:17 -04:00
comments cleanup
All checks were successful
ci/woodpecker/pr/cargo-checks Pipeline was successful
6912708cfb
modulatingforce changed title from WIP: Exec Body Fn should be passed Parent BotAction to Exec Body Fn should be passed Parent BotAction 2024-03-25 16:27:03 -04:00
modulatingforce merged commit befb742b81 into main 2024-03-25 16:29:44 -04:00
modulatingforce deleted branch parent-botaction-to-child-fn 2024-03-25 16:29:44 -04:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: modulatingforce/forcebot_rs#43
No description provided.