Agentorie_Database::dates_to_iso8601( $conversations ) ) ); } /** * Handle get messages request. * * @return void */ public function handle_get_messages() { if ( ! Agentorie_API_Helpers::verify_admin_access() ) { return; } $session_id = Agentorie_API_Helpers::get_input( 'session_id', '', 'key' ); $after_id = Agentorie_API_Helpers::get_input( 'after_id', 0, 'absint' ); if ( empty( $session_id ) || ! Agentorie_Session::validate_session_id( $session_id ) ) { Agentorie_API_Helpers::send_error( __( 'Invalid session ID.', 'agentorie-chat' ) ); } $messages = Agentorie_Database::get_messages( $session_id, 100, $after_id ); Agentorie_Database::mark_messages_read( $session_id ); $session = Agentorie_Session::get_or_create( $session_id ); Agentorie_API_Helpers::send_success( array( 'messages' => Agentorie_Database::dates_to_iso8601( $messages ), 'session' => Agentorie_Database::dates_to_iso8601( $session->get_all() ), ) ); } /** * Handle send message request. * * @return void */ public function handle_send_message() { if ( ! Agentorie_API_Helpers::verify_admin_access() ) { return; } $session_id = Agentorie_API_Helpers::get_input( 'session_id', '', 'key' ); $message = Agentorie_API_Helpers::get_input( 'message', '', 'textarea' ); if ( empty( $session_id ) || empty( $message ) ) { Agentorie_API_Helpers::send_error( __( 'Session ID and message are required.', 'agentorie-chat' ) ); } if ( ! Agentorie_Session::validate_session_id( $session_id ) ) { Agentorie_API_Helpers::send_error( __( 'Invalid session ID.', 'agentorie-chat' ) ); } $message = Agentorie_API_Helpers::sanitize_message( $message, 1000 ); $admin_id = get_current_user_id(); $session = Agentorie_Session::get_or_create( $session_id ); $takeover_activated = false; if ( ! $session->is_admin_takeover() ) { $session->set_admin_takeover( true, $admin_id ); $takeover_activated = true; } $message_id = Agentorie_Database::insert_message( array( 'session_id' => $session_id, 'role' => 'assistant', 'message' => $message, 'is_admin' => 1, ) ); $session->increment_messages(); $session->set_last_message( $message ); $session->save(); $session->sync_to_database(); // Notify SaaS via WebSocket. $saas = Agentorie_API_SaaS::get_instance(); $saas->send_admin_message( $session_id, $message, $admin_id ); Agentorie_API_Helpers::send_success( array( 'message_id' => $message_id, 'takeover_activated' => $takeover_activated, ) ); } /** * Handle takeover request. * * @return void */ public function handle_takeover() { if ( ! Agentorie_API_Helpers::verify_admin_access() ) { return; } $session_id = Agentorie_API_Helpers::get_input( 'session_id', '', 'key' ); if ( empty( $session_id ) || ! Agentorie_Session::validate_session_id( $session_id ) ) { Agentorie_API_Helpers::send_error( __( 'Invalid session ID.', 'agentorie-chat' ) ); } $admin_id = get_current_user_id(); $session = Agentorie_Session::get_or_create( $session_id ); $session->set_admin_takeover( true, $admin_id ); $session->save(); $session->sync_to_database(); // Insert system notification message. $admin_name = get_user_meta( $admin_id, 'agentorie_chat_livechat_name', true ); if ( empty( $admin_name ) ) { $user = get_userdata( $admin_id ); $admin_name = $user ? $user->display_name : __( 'Advisor', 'agentorie-chat' ); } Agentorie_Database::insert_message( array( 'session_id' => $session_id, 'role' => 'assistant', 'message' => sprintf( /* translators: %s: admin display name who took over the conversation */ __( '%s is now assisting you', 'agentorie-chat' ), $admin_name ), 'is_admin' => 2, // 2 = system message 'admin_id' => $admin_id, 'is_read' => 1, ) ); // Notify SaaS via WebSocket. $saas = Agentorie_API_SaaS::get_instance(); $saas->takeover_conversation( $session_id, $admin_id ); Agentorie_API_Helpers::send_success( array( 'takeover' => true ) ); } /** * Handle release request. * * @return void */ public function handle_release() { if ( ! Agentorie_API_Helpers::verify_admin_access() ) { return; } $session_id = Agentorie_API_Helpers::get_input( 'session_id', '', 'key' ); if ( empty( $session_id ) || ! Agentorie_Session::validate_session_id( $session_id ) ) { Agentorie_API_Helpers::send_error( __( 'Invalid session ID.', 'agentorie-chat' ) ); } $admin_id = get_current_user_id(); $session = Agentorie_Session::get_or_create( $session_id ); $session->set_admin_takeover( false ); $session->save(); $session->sync_to_database(); // Insert system notification message. $admin_name = get_user_meta( $admin_id, 'agentorie_chat_livechat_name', true ); if ( empty( $admin_name ) ) { $user = get_userdata( $admin_id ); $admin_name = $user ? $user->display_name : __( 'Advisor', 'agentorie-chat' ); } $bot_name = agentorie_chat_get_setting( 'bot_name', __( 'the assistant', 'agentorie-chat' ) ); Agentorie_Database::insert_message( array( 'session_id' => $session_id, 'role' => 'assistant', 'message' => sprintf( /* translators: %1$s: admin display name, %2$s: bot/assistant name */ __( '%1$s has handed you back to %2$s', 'agentorie-chat' ), $admin_name, $bot_name ), 'is_admin' => 2, // 2 = system message 'admin_id' => $admin_id, 'is_read' => 1, ) ); // Notify SaaS via WebSocket. $saas = Agentorie_API_SaaS::get_instance(); $saas->release_conversation( $session_id, $admin_id ); Agentorie_API_Helpers::send_success( array( 'released' => true ) ); } /** * Handle presence request. * * @return void */ public function handle_presence() { if ( ! Agentorie_API_Helpers::verify_admin_access() ) { return; } $active = Agentorie_API_Helpers::get_input( 'active', true, 'bool' ); $admin_id = get_current_user_id(); $user = get_userdata( $admin_id ); $admin_name = $user ? $user->display_name : 'Admin'; Agentorie_API_Helpers::set_admin_presence( $active ); // Notify SaaS. $saas = Agentorie_API_SaaS::get_instance(); $saas_response = $saas->update_presence( $admin_id, $admin_name, $active ); $online_count = 0; $max_admins = 1; if ( is_wp_error( $saas_response ) ) { // Check if it's a limit error. $error_data = $saas_response->get_error_data(); if ( isset( $error_data['error_code'] ) && 'admin_limit_reached' === $error_data['error_code'] ) { $err_online = isset( $error_data['online_count'] ) ? (int) $error_data['online_count'] : 0; $err_max = isset( $error_data['max_admins'] ) ? (int) $error_data['max_admins'] : 1; Agentorie_API_Helpers::send_error( $saas_response->get_error_message(), array( 'error_code' => 'admin_limit_reached', 'online_count' => $err_online, 'max_admins' => $err_max, ) ); return; } } elseif ( is_array( $saas_response ) ) { $online_count = isset( $saas_response['online_count'] ) ? (int) $saas_response['online_count'] : 0; $max_admins = isset( $saas_response['max_admins'] ) ? (int) $saas_response['max_admins'] : 1; } Agentorie_API_Helpers::send_success( array( 'active' => $active, 'online_count' => $online_count, 'max_admins' => $max_admins, ) ); } /** * Handle presence ping request (heartbeat). * * Important: The ping does NOT change the online/offline status. * It only keeps last_ping updated for admins already online. * * @return void */ public function handle_presence_ping() { if ( ! Agentorie_API_Helpers::verify_admin_access() ) { return; } $admin_id = get_current_user_id(); // Check first if the admin is already online. $current_status = Agentorie_API_Helpers::is_admin_online(); // If admin is offline, do nothing (don't force them online). if ( ! $current_status ) { Agentorie_API_Helpers::send_success( array( 'pinged' => false, 'status' => 'offline', 'message' => 'Admin is offline, ping skipped', ) ); return; } // If admin is online, maintain the ping. $user = get_userdata( $admin_id ); $admin_name = $user ? $user->display_name : 'Admin'; // Maintain current status (true since verified above). Agentorie_API_Helpers::set_admin_presence( true ); // Ping SaaS to maintain last_ping. $saas = Agentorie_API_SaaS::get_instance(); $saas_response = $saas->update_presence( $admin_id, $admin_name, true ); $online_count = 0; $max_admins = 1; if ( ! is_wp_error( $saas_response ) && is_array( $saas_response ) ) { $online_count = isset( $saas_response['online_count'] ) ? (int) $saas_response['online_count'] : 0; $max_admins = isset( $saas_response['max_admins'] ) ? (int) $saas_response['max_admins'] : 1; } Agentorie_API_Helpers::send_success( array( 'pinged' => true, 'online_count' => $online_count, 'max_admins' => $max_admins, ) ); } /** * Handle mark read request. * * @return void */ public function handle_mark_read() { if ( ! Agentorie_API_Helpers::verify_admin_access() ) { return; } $session_id = Agentorie_API_Helpers::get_input( 'session_id', '', 'key' ); if ( empty( $session_id ) || ! Agentorie_Session::validate_session_id( $session_id ) ) { Agentorie_API_Helpers::send_error( __( 'Invalid session ID.', 'agentorie-chat' ) ); } Agentorie_Database::mark_messages_read( $session_id ); Agentorie_API_Helpers::send_success(); } /** * Handle delete conversation request. * * @return void */ public function handle_delete_conversation() { if ( ! Agentorie_API_Helpers::verify_admin_access() ) { return; } $session_id = Agentorie_API_Helpers::get_input( 'session_id', '', 'key' ); if ( empty( $session_id ) || ! Agentorie_Session::validate_session_id( $session_id ) ) { Agentorie_API_Helpers::send_error( __( 'Invalid session ID.', 'agentorie-chat' ) ); } Agentorie_Database::delete_session( $session_id ); Agentorie_API_Helpers::send_success( array( 'deleted' => true ) ); } /** * Handle update flag request (for human_requested and negotiate_detected). * * Called by LiveChat WebSocket when flags are detected in bot responses. * * @return void */ public function handle_update_flag() { if ( ! Agentorie_API_Helpers::verify_admin_access() ) { return; } $session_id = Agentorie_API_Helpers::get_input( 'session_id', '', 'key' ); $flag = Agentorie_API_Helpers::get_input( 'flag', '', 'key' ); $value = Agentorie_API_Helpers::get_input( 'value', 0, 'int' ); if ( empty( $session_id ) || ! Agentorie_Session::validate_session_id( $session_id ) ) { Agentorie_API_Helpers::send_error( __( 'Invalid session ID.', 'agentorie-chat' ) ); } // Only allow specific flags. $allowed_flags = array( 'human_requested', 'negotiate_detected' ); if ( ! in_array( $flag, $allowed_flags, true ) ) { Agentorie_API_Helpers::send_error( __( 'Invalid flag.', 'agentorie-chat' ) ); } $session = Agentorie_Session::get_or_create( $session_id ); // Update the flag based on type. if ( 'human_requested' === $flag ) { $session->set_human_requested( (bool) $value ); } elseif ( 'negotiate_detected' === $flag ) { $session->set_negotiate_detected( (bool) $value ); } $session->save(); $session->sync_to_database(); Agentorie_API_Helpers::send_success( array( 'updated' => true, 'flag' => $flag, 'value' => $value, ) ); } }