2023-03-18 03:25:22 +00:00
use async_openai ::{ Client , types ::{ CreateChatCompletionRequestArgs , ChatCompletionRequestMessageArgs , Role } } ;
2023-02-17 08:38:32 +00:00
use crate ::modules ::Command ;
2023-02-18 06:47:35 +00:00
use toml ::Value ;
2023-02-17 11:58:25 +00:00
use serde ::Deserialize ;
2023-03-18 03:25:22 +00:00
use regex ::Regex ;
2023-02-19 21:08:48 +00:00
2023-02-17 11:58:25 +00:00
#[ derive(Deserialize) ]
struct Config {
nick : String ,
openai : String ,
2023-02-17 18:59:31 +00:00
model : String ,
2023-02-17 11:58:25 +00:00
accents : String ,
personalities : String ,
}
2023-03-18 03:25:22 +00:00
2023-02-17 08:38:32 +00:00
pub struct Ai ;
2023-03-18 03:25:22 +00:00
2023-02-17 08:38:32 +00:00
impl Command for Ai {
fn handle ( & self , message : & str ) -> Vec < String > {
let mut responses = Vec ::new ( ) ;
2023-02-17 11:58:25 +00:00
let config_str = std ::fs ::read_to_string ( " config.toml " ) . unwrap ( ) ;
let config_value = config_str . parse ::< Value > ( ) . unwrap ( ) ;
2023-03-18 03:25:22 +00:00
let config : Config = config_value . try_into ( ) . unwrap ( ) ;
if message . starts_with ( " : " ) & & message . contains ( " PRIVMSG " ) & & message . contains ( & config . nick ) {
let channel = message . split ( " PRIVMSG " ) . nth ( 1 ) . and_then ( | s | s . splitn ( 2 , ' ' ) . next ( ) ) . unwrap ( ) ;
let cleaned_message = message . replace ( & format! ( " {} " , config . nick ) , " " ) ;
println! ( " {} " , cleaned_message ) ;
let user_message = cleaned_message . split ( & format! ( " PRIVMSG {} : " , channel . to_string ( ) ) ) . nth ( 1 ) . unwrap ( ) ;
let parts : Vec < & str > = message . splitn ( 2 , ' ' ) . collect ( ) ;
2023-02-17 08:38:32 +00:00
let username = parts [ 0 ] . trim_start_matches ( ':' ) . split ( " ! " ) . next ( ) . unwrap ( ) ;
2023-03-18 03:25:22 +00:00
2023-02-17 08:38:32 +00:00
let rt = tokio ::runtime ::Runtime ::new ( ) . unwrap ( ) ;
2023-03-18 03:25:22 +00:00
let result = rt . block_on ( ai ( & user_message , & username , & channel , & config ) ) ;
2023-02-17 08:38:32 +00:00
responses . extend ( result ) ;
}
responses
}
}
2023-03-18 03:25:22 +00:00
async fn ai ( user_message : & str , username : & str , channel : & str , config : & Config ) -> Vec < String > {
let api_key = & config . openai ;
2023-02-17 08:38:32 +00:00
let client = Client ::new ( ) . with_api_key ( api_key ) ;
2023-03-18 03:25:22 +00:00
let request = CreateChatCompletionRequestArgs ::default ( )
. model ( & config . model )
. messages ( [
ChatCompletionRequestMessageArgs ::default ( )
. role ( Role ::System )
. content ( format! ( " Respond {} as you are chatting as {} , The following is a chat message to you from {} dont mention that you are who you are they can see that: " , config . accents , config . personalities , username ) )
. build ( )
. unwrap ( ) ,
ChatCompletionRequestMessageArgs ::default ( )
. role ( Role ::User )
. content ( user_message . to_string ( ) )
. build ( )
. unwrap ( ) ,
] )
. max_tokens ( 256_ u16 )
2023-02-17 08:38:32 +00:00
. build ( )
. unwrap ( ) ;
2023-03-18 03:25:22 +00:00
let response = client . chat ( ) . create ( request ) . await . unwrap ( ) ;
let response_text = response . choices . first ( ) . unwrap ( ) . message . content . trim ( ) . to_string ( ) ;
let regex = Regex ::new ( r # ""|[gG][1iI][rR]\s"# ) . unwrap ( ) ; // THIS IS FUCKING UP EVERYTHING
let response_text = regex . replace_all ( & response_text , " " ) . trim ( ) . to_string ( ) ;
println! ( " {} " , response_text ) ;
2023-02-17 08:38:32 +00:00
let response_lines = response_text . split ( " \n " ) . filter ( | line | ! line . trim ( ) . is_empty ( ) ) ;
let mut responses = Vec ::new ( ) ;
2023-03-18 03:25:22 +00:00
let mut line_count = 0 ;
2023-02-17 08:38:32 +00:00
for line in response_lines {
2023-03-18 03:25:22 +00:00
if line . contains ( " * " ) {
let parts : Vec < & str > = line . split ( " * " ) . collect ( ) ;
for ( i , part ) in parts . iter ( ) . enumerate ( ) {
if i % 2 = = 1 {
let action = part . to_lowercase ( ) ;
responses . push ( format! ( " PRIVMSG {} : \x01 ACTION {} \x01 \r \n " , channel , action ) ) ;
} else {
let message = part . trim ( ) . to_string ( ) ;
responses . push ( format! ( " PRIVMSG {} : {} \r \n " , channel , message ) ) ;
}
}
} else {
let response_line = if line_count = = 0 & & ! line . contains ( & username ) {
format! ( " PRIVMSG {} : \x03 13 {} \x0f : {} \r \n " , channel , username , line )
} else {
format! ( " PRIVMSG {} : {} \r \n " , channel , line )
} ;
responses . push ( response_line ) ;
}
line_count + = 1 ;
2023-02-17 08:38:32 +00:00
}
2023-03-18 03:25:22 +00:00
2023-02-17 08:38:32 +00:00
responses
2023-03-18 03:25:22 +00:00
}