set_basename( false, __FILE__ ); return; } // The SDK lives in vendor/freemius/ (bundled in release builds). Without it, e.g. in a // bare development checkout, the plugin still runs: every botshido_fs() use is guarded. if ( file_exists( dirname( __FILE__ ) . '/vendor/freemius/start.php' ) ) { function botshido_fs() { global $botshido_fs; if ( !isset( $botshido_fs ) ) { require_once dirname( __FILE__ ) . '/vendor/freemius/start.php'; $botshido_fs = fs_dynamic_init( array( 'id' => '40006', 'slug' => 'botshido', 'premium_slug' => 'botshido-pro', 'type' => 'plugin', 'public_key' => 'pk_743b146a23b6508350e934fd15e76', 'is_premium' => false, 'premium_suffix' => 'Pro', 'has_addons' => false, 'has_paid_plans' => true, 'menu' => array( 'slug' => 'botshido', 'first-path' => 'admin.php?page=botshido-setup', 'support' => false, ), 'is_live' => true, 'is_org_compliant' => true, ) ); } return $botshido_fs; } botshido_fs(); do_action( 'botshido_fs_loaded' ); } define( 'NINJAIBOT_VERSION', '1.2.5' ); // Database schema version, independent of the plugin version. Bump this (and // only this) when shipping a schema change; see NinjaiBot_Plugin::maybe_run_upgrade_routines(). define( 'NINJAIBOT_DB_VERSION', '1.2.3' ); define( 'NINJAIBOT_PLUGIN_FILE', __FILE__ ); define( 'NINJAIBOT_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); define( 'NINJAIBOT_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); if ( !function_exists( 'ninjaibot_asset_version' ) ) { /** * Cache-busting version string for a plugin asset. * * NINJAIBOT_VERSION only changes on release, so CSS/JS edits shipped between * releases stay stuck in browser caches. Using the file's mtime invalidates * the cache whenever the asset actually changes. * * @param string $relative_path Asset path relative to the plugin root. * @return string */ function ninjaibot_asset_version( $relative_path ) { $absolute_path = NINJAIBOT_PLUGIN_DIR . ltrim( $relative_path, '/' ); $mtime = ( file_exists( $absolute_path ) ? filemtime( $absolute_path ) : false ); return ( false !== $mtime ? (string) $mtime : NINJAIBOT_VERSION ); } } if ( !function_exists( 'ninjaibot_get_option_value' ) ) { /** * Read an option, falling back to $default when the stored value is empty. * * get_option()'s own $default only applies when the option row is missing. On * chatbot-scoped admin pages the value comes from the chatbot's ui_settings, * where unset fields are stored as empty strings — so get_option() returns '' * and the default is never used. Admin fields that need a visible value (color * pickers, image URLs) have to fall back explicitly. * * Intended for string-valued options: an integer 0 is returned untouched. * * @param string $option Option name. * @param mixed $default Value to use when the option is empty or missing. * @return mixed */ function ninjaibot_get_option_value( $option, $default = '' ) { $value = get_option( $option, $default ); if ( is_string( $value ) ) { $value = trim( $value ); } if ( '' === $value || null === $value || false === $value ) { return $default; } return $value; } } require_once NINJAIBOT_PLUGIN_DIR . 'core/class-ninjaibot-loader.php'; require_once NINJAIBOT_PLUGIN_DIR . 'database/class-ninjaibot-database-manager.php'; require_once NINJAIBOT_PLUGIN_DIR . 'chatbots/class-ninjaibot-chatbot-model.php'; require_once NINJAIBOT_PLUGIN_DIR . 'chatbots/class-ninjaibot-chatbot-context.php'; require_once NINJAIBOT_PLUGIN_DIR . 'chatbots/class-ninjaibot-chatbot-storage.php'; require_once NINJAIBOT_PLUGIN_DIR . 'chatbots/class-ninjaibot-chatbot-manager.php'; require_once NINJAIBOT_PLUGIN_DIR . 'chatbots/class-ninjaibot-chatbot-config-resolver.php'; require_once NINJAIBOT_PLUGIN_DIR . 'chatbots/class-ninjaibot-content-block-storage.php'; require_once NINJAIBOT_PLUGIN_DIR . 'api/class-ninjaibot-api-manager.php'; require_once NINJAIBOT_PLUGIN_DIR . 'includes/sanitization.php'; require_once NINJAIBOT_PLUGIN_DIR . 'includes/i18n/ninjaibot-i18n.php'; require_once NINJAIBOT_PLUGIN_DIR . 'includes/privacy/ninjaibot-privacy.php'; require_once NINJAIBOT_PLUGIN_DIR . 'includes/llm/llm-provider-interface.php'; require_once NINJAIBOT_PLUGIN_DIR . 'includes/llm/providers/class-ninjaibot-openai-provider.php'; require_once NINJAIBOT_PLUGIN_DIR . 'includes/llm/providers/class-ninjaibot-mistral-provider.php'; require_once NINJAIBOT_PLUGIN_DIR . 'includes/llm/providers/class-ninjaibot-anthropic-provider.php'; require_once NINJAIBOT_PLUGIN_DIR . 'includes/llm/providers/class-ninjaibot-grok-provider.php'; require_once NINJAIBOT_PLUGIN_DIR . 'includes/llm/class-ninjaibot-llm-response-normalizer.php'; require_once NINJAIBOT_PLUGIN_DIR . 'includes/llm/class-ninjaibot-llm-request-builder.php'; require_once NINJAIBOT_PLUGIN_DIR . 'includes/llm/class-ninjaibot-llm-service.php'; require_once NINJAIBOT_PLUGIN_DIR . 'includes/database/class-ninjaibot-kb-reindex-queue.php'; require_once NINJAIBOT_PLUGIN_DIR . 'includes/database/class-ninjaibot-cleanup-service.php'; require_once NINJAIBOT_PLUGIN_DIR . 'includes/database/ninjaibot-database-functions.php'; // TODO: Deferred to the project roadmap; reimplement and validate before restoring. // require_once NINJAIBOT_PLUGIN_DIR . 'includes/integrations/events-calendar-context.php'; // TODO: Deferred to the project roadmap; reimplement and validate before restoring. // require_once NINJAIBOT_PLUGIN_DIR . 'includes/integrations/edd-context.php'; require_once NINJAIBOT_PLUGIN_DIR . 'includes/ajax/ninjaibot-ajax-functions.php'; // Pro modules: Freemius strips every *__premium_only.php file from the Free // build, so they are loaded only when present and all shared code checks // class_exists() / function_exists() before using them (tests/free-build-split.php). // The frontend degrades on its own: e.g. the script loader emits // handoff.enabled = 0 when NinjaiBot_Availability_Service is missing. foreach ( array( 'includes/llm/class-ninjaibot-embedding-service__premium_only.php', 'includes/database/ninjaibot-kb-url-import__premium_only.php', 'includes/integrations/woocommerce-context__premium_only.php', 'includes/class-ninjaibot-availability-service__premium_only.php', 'includes/ajax/class-ninjaibot-handoff-ajax__premium_only.php', 'includes/ninjaibot-pro-features__premium_only.php' ) as $ninjaibot_pro_file ) { if ( file_exists( NINJAIBOT_PLUGIN_DIR . $ninjaibot_pro_file ) ) { require_once NINJAIBOT_PLUGIN_DIR . $ninjaibot_pro_file; } } unset($ninjaibot_pro_file); require_once NINJAIBOT_PLUGIN_DIR . 'includes/ajax/class-ninjaibot-template-ajax.php'; require_once NINJAIBOT_PLUGIN_DIR . 'includes/admin/botshido-inline-assets.php'; require_once NINJAIBOT_PLUGIN_DIR . 'includes/admin/class-ninjaibot-admin-chatbot-context.php'; require_once NINJAIBOT_PLUGIN_DIR . 'includes/admin/class-ninjaibot-kb-admin-ajax.php'; require_once NINJAIBOT_PLUGIN_DIR . 'includes/admin/class-ninjaibot-content-block-admin.php'; require_once NINJAIBOT_PLUGIN_DIR . 'includes/admin/class-ninjaibot-conversation-admin.php'; require_once NINJAIBOT_PLUGIN_DIR . 'includes/admin/class-ninjaibot-settings-admin.php'; require_once NINJAIBOT_PLUGIN_DIR . 'includes/admin/class-ninjaibot-legacy-admin.php'; require_once NINJAIBOT_PLUGIN_DIR . 'admin/class-ninjaibot-admin.php'; require_once NINJAIBOT_PLUGIN_DIR . 'includes/admin/class-ninjaibot-setup-wizard.php'; require_once NINJAIBOT_PLUGIN_DIR . 'public/class-ninjaibot-frontend-script-loader.php'; require_once NINJAIBOT_PLUGIN_DIR . 'public/class-ninjaibot-chat-renderer.php'; require_once NINJAIBOT_PLUGIN_DIR . 'public/class-ninjaibot-shortcode-handler.php'; require_once NINJAIBOT_PLUGIN_DIR . 'public/class-ninjaibot-public.php'; require_once NINJAIBOT_PLUGIN_DIR . 'core/class-ninjaibot-activator.php'; require_once NINJAIBOT_PLUGIN_DIR . 'core/class-ninjaibot-deactivator.php'; require_once NINJAIBOT_PLUGIN_DIR . 'core/class-ninjaibot-plugin.php'; require_once NINJAIBOT_PLUGIN_DIR . 'includes/uninstall-cleanup.php'; if ( function_exists( 'botshido_fs' ) ) { botshido_fs()->add_action( 'after_uninstall', 'ninjaibot_uninstall_cleanup' ); } else { register_uninstall_hook( __FILE__, 'ninjaibot_uninstall_cleanup' ); } register_activation_hook( __FILE__, array('NinjaiBot_Activator', 'activate') ); register_deactivation_hook( __FILE__, array('NinjaiBot_Deactivator', 'deactivate') ); if ( !function_exists( 'ninjaibot_initialize_new_site' ) ) { /** * When the plugin is network-active, run the per-site activation routine on * every newly created subsite (tables, default options, cleanup cron). * * @param WP_Site $new_site The site being initialized. */ function ninjaibot_initialize_new_site( $new_site ) { if ( !is_multisite() ) { return; } if ( !function_exists( 'is_plugin_active_for_network' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } if ( !is_plugin_active_for_network( plugin_basename( NINJAIBOT_PLUGIN_FILE ) ) ) { return; } switch_to_blog( (int) $new_site->blog_id ); NinjaiBot_Activator::activate_single_site(); restore_current_blog(); } } add_action( 'wp_initialize_site', 'ninjaibot_initialize_new_site', 100 ); $ninjaibot_plugin = new NinjaiBot_Plugin(); $ninjaibot_plugin->run();