Current Path : /storage/v11800/affypharma/public_html/wp-content/plugins/ai-engine/classes/

Linux v11800 5.3.0-1023-aws #25~18.04.1-Ubuntu SMP Fri Jun 5 15:19:18 UTC 2020 aarch64

Upload File :
Current File : /storage/v11800/affypharma/public_html/wp-content/plugins/ai-engine/classes/core.php
<?php

require_once( MWAI_PATH . '/vendor/autoload.php' );
require_once( MWAI_PATH . '/constants/init.php' );

define( 'MWAI_IMG_WAND', MWAI_URL . '/images/wand.png' );
define( 'MWAI_IMG_WAND_HTML', "<img style='height: 22px; margin-bottom: -5px; margin-right: 8px;'
  src='" . MWAI_IMG_WAND . "' alt='AI Wand' />" );
define( 'MWAI_IMG_WAND_HTML_XS', "<img style='height: 16px; margin-bottom: -2px;'
  src='" . MWAI_IMG_WAND . "' alt='AI Wand' />" );
	
class Meow_MWAI_Core
{
	public $admin = null;
	public $is_rest = false;
	public $is_cli = false;
	public $site_url = null;
	public $files = null;
	public $tasks = null;
	public $magicWand = null;
	private $option_name = 'mwai_options';
	private $themes_option_name = 'mwai_themes';
	private $chatbots_option_name = 'mwai_chatbots';
	private $nonce = null;

	public $chatbot = null;
	public $discussions = null;

	public function __construct() {
		$this->site_url = get_site_url();
		$this->is_rest = MeowCommon_Helpers::is_rest();
		$this->is_cli = defined( 'WP_CLI' );
		$this->files = new Meow_MWAI_Modules_Files( $this );
		$this->tasks = new Meow_MWAI_Modules_Tasks( $this );
		if ( $this->get_option( 'module_suggestions' ) ) {
			$this->magicWand = new Meow_MWAI_Modules_Wand( $this );
		}

		add_action( 'plugins_loaded', array( $this, 'init' ) );
		add_action( 'wp_register_script', array( $this, 'register_scripts' ) );
		add_action( 'wp_enqueue_scripts', array( $this, 'register_scripts' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'register_scripts' ) );
	}

	#region Init & Scripts
	function init() {
		global $mwai;
		$this->chatbot = null;
		$this->discussions = null;
		new Meow_MWAI_Modules_Security( $this );

		// REST API
		if ( $this->is_rest ) {
			new Meow_MWAI_Rest( $this );
		}

		// WP Admin
		if ( is_admin() ) {
			new Meow_MWAI_Admin( $this );
		}

		// Administrator in WP Admin
		if ( is_admin() && current_user_can( 'manage_options' ) ) {
			$module_advisor = $this->get_option( 'module_advisor' );
			if ( $module_advisor ) {
				new Meow_MWAI_Modules_Advisor( $this );
			}
		}

		// Chatbots & Discussions
		if ( $this->get_option( 'module_chatbots' ) ) {
			$this->chatbot = new Meow_MWAI_Modules_Chatbot();
			$this->discussions = new Meow_MWAI_Modules_Discussions();
		}

		// Advanced Core
		if ( class_exists( 'MeowPro_MWAI_Core' ) ) {
			new MeowPro_MWAI_Core( $this );
		}

		// Simple API
		$mwai = new Meow_MWAI_API( $this->chatbot, $this->discussions );
	}

	public function register_scripts() {
		wp_register_script( 'mwai_highlight', MWAI_URL . 'vendor/highlightjs/highlight.min.js', [], '11.7', false );
	}

	#endregion

	#region Roles & Capabilities
	function can_start_session() {
		return apply_filters( 'mwai_allow_session', true );
	}

	function can_access_settings() {
		return apply_filters( 'mwai_allow_setup', current_user_can( 'manage_options' ) );
	}

	function can_access_features() {
		$editor_or_admin = current_user_can( 'editor' ) || current_user_can( 'administrator' );
		return apply_filters( 'mwai_allow_usage', $editor_or_admin );
	}
	
	function can_access_public_api( $feature, $extra ) {
		$logged_in = is_user_logged_in();
		return apply_filters( 'mwai_allow_public_api', $logged_in, $feature, $extra );
	}

	#endregion

	#region AI-Related Helpers
	function run_query( $query, $streamCallback = null, $markdown = false ) {
		$envId = !empty( $query->envId ) ? $query->envId : null;
		$engine = Meow_MWAI_Engines_Factory::get( $this, $envId );

		// If the engine is not set, we need to set it to the default one.
		if ( !$envId || !$engine->retrieve_model_info( $query->model ) ) {
			if ( $query instanceof Meow_MWAI_Query_Text ) {
				$this->set_if_empty_defaults( $query, 'ai_default_env', 'ai_default_model' );
			}
			if ( $query instanceof Meow_MWAI_Query_Embed ) {
				$this->set_if_empty_defaults( $query, 'ai_embeddings_default_env', 'ai_embeddings_default_model' );
			}
			else if ( $query instanceof Meow_MWAI_Query_Image ) {
				$this->set_if_empty_defaults( $query, 'ai_images_default_env', 'ai_images_default_model' );
			}
			else if ( $query instanceof Meow_MWAI_Query_Transcribe ) {
				$this->set_if_empty_defaults( $query, 'ai_audio_default_env', 'ai_audio_default_model' );
			}
			$engine = Meow_MWAI_Engines_Factory::get( $this, $query->envId );
		}

		// Let's run the query.
		$reply = $engine->run( $query, $streamCallback );
		
		// Let's allow to modify the reply before it is sent.
		if ( $markdown ) {
			if ( $query instanceof Meow_MWAI_Query_Image ) {
				$reply->result = "";
				foreach ( $reply->results as $result ) {
					$reply->result .= "![Image]($result)\n";
				}
			}
		}

		return $reply;
	}
	
	private function set_if_empty_defaults( $query, $envOption, $modelOption ) {
		$defaultEnv = $this->get_option( $envOption );
		$defaultModel = $this->get_option( $modelOption );
		if ( empty( $defaultEnv ) || empty( $defaultModel ) ) {
			throw new Exception( 'AI Engine: The default environment and model are not set.' );
		}
		$query->set_env_id( $defaultEnv );
		$query->set_model( $defaultModel );
	}	
	#endregion

	#region Text-Related Helpers

	// Clean the text perfectly, resolve shortcodes, etc, etc.
  function clean_text( $rawText = "" ) {
		$text = html_entity_decode( $rawText );
		$text = wp_strip_all_tags( $text );
		$text = preg_replace( '/[\r\n]+/', "\n", $text );
		$text = preg_replace( '/\n+/', "\n", $text );
		$text = preg_replace( '/\t+/', "\t", $text );
		return $text . " ";
  }

  // Make sure there are no duplicate sentences, and keep the length under a maximum length.
  function clean_sentences( $text, $maxLength = null ) {
		// Step 1: Identify URLs and replace them with a placeholder.
		$urlPattern = '/\bhttps?:\/\/[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|\/))/';
		preg_match_all($urlPattern, $text, $urls);
		$urlPlaceholders = array();
		foreach ($urls[0] as $index => $url) {
			$placeholder = "{urlPlaceholder" . $index . "}";
			$text = str_replace($url, $placeholder, $text);
			$urlPlaceholders[$placeholder] = $url;
		}
	
		$maxLength = (int)($maxLength ? $maxLength : $this->get_option( 'context_max_length', 4096 ));
		$sentences = preg_split('/(?<=[.?!。.!?])\s+/u', $text, -1, PREG_SPLIT_NO_EMPTY);
		$hashes = array();
		$uniqueSentences = array();
		$total = 0;
	
		foreach ( $sentences as $sentence ) {
			$sentence = preg_replace( '/^[\pZ\pC]+|[\pZ\pC]+$/u', '', $sentence );
			$hash = md5( $sentence );
			if ( !in_array( $hash, $hashes ) ) {
				$length = mb_strlen( $sentence, 'UTF-8' );
				if ( $total + $length > $maxLength ) {
					continue;
				}
				$hashes[] = $hash;
				$uniqueSentences[] = $sentence;
				$total += $length;
			}
		}
	
		$freshText = implode( " ", $uniqueSentences );
	
		// Step 3: Restore URLs in the final text.
		foreach ($urlPlaceholders as $placeholder => $url) {
			$freshText = str_replace($placeholder, $url, $freshText);
		}
	
		$freshText = preg_replace( '/^[\pZ\pC]+|[\pZ\pC]+$/u', '', $freshText );
		return $freshText;
	}	

	function get_post_content( $postId ) {
		$post = get_post( $postId );
		if ( !$post ) {
			return false;
		}
		$text = apply_filters( 'mwai_pre_post_content', $post->post_content, $postId );
		$pattern = '/\[mwai_.*?\]/';
    $text = preg_replace( $pattern, '', $text );
		if ( $this->get_option( 'resolve_shortcodes' ) ) {
			$text = apply_filters( 'the_content', $text );
		}
		else {
			$pattern = "/\[[^\]]+\]/";
    	$text = preg_replace( $pattern, '', $text );
			$pattern = "/<!--\s*\/?wp:[^\>]+-->/";
			$text = preg_replace( $pattern, '', $text );
		}
		$text = $this->clean_text( $text );
		$text = $this->clean_sentences( $text );
		$text = apply_filters( 'mwai_post_content', $text, $postId );
		return $text;
	}

	function markdown_to_html( $content ) {
		$Parsedown = new Parsedown();
		$content = $Parsedown->text( $content );
		return $content;
	}

	function get_post_language( $postId ) {
		$locale = get_locale();
		$code = strtolower( substr( $locale, 0, 2 ) );
		$humanLanguage = strtr( $code, MWAI_ALL_LANGUAGES );
		$lang = apply_filters( 'wpml_post_language_details', null, $postId );
		if ( !empty( $lang ) ) {
			$locale = $lang['locale'];
			$humanLanguage = $lang['display_name'];
		}
		return strtolower( "$locale ($humanLanguage)" );
	}
	#endregion

 	#region Image-Related Helpers
	static function is_image( $file ) {
		$mimeType = Meow_MWAI_Core::get_mime_type( $file );
		if ( strpos( $mimeType, 'image' ) !== false ) {
			return true;
		}
		return false;
	}

	static function get_mime_type( $file ) {
		$mimeType = null;

		// Let's try to use mime_content_type if the function exists
		$isUrl = filter_var( $file, FILTER_VALIDATE_URL );
		if ( !$isUrl && function_exists( 'mime_content_type' ) ) {
			$mimeType = mime_content_type( $file );
		}

		// Otherwise, let's check the file extension (which can actually also be an URL)
		if ( !$mimeType ) {
			$extension = pathinfo( $file, PATHINFO_EXTENSION );
			$extension = strtolower( $extension );
			$mimeTypes = [
				'jpg' => 'image/jpeg',
				'jpeg' => 'image/jpeg',
				'png' => 'image/png',
				'gif' => 'image/gif',
				'webp' => 'image/webp',
				'bmp' => 'image/bmp',
				'tiff' => 'image/tiff',
				'tif' => 'image/tiff',
				'svg' => 'image/svg+xml',
				'ico' => 'image/x-icon',
				'pdf' => 'application/pdf',
			];
			$mimeType = isset( $mimeTypes[$extension] ) ? $mimeTypes[$extension] : null;
		}

		return $mimeType;
	}

	function download_image( $url ) {
		$args = array( 'timeout' => 60, );
		$response = wp_safe_remote_get( $url, $args );
		if ( is_wp_error( $response ) ) {
			throw new Exception( $response->get_error_message() );
		}
		$output = wp_remote_retrieve_body( $response );
		if ( is_wp_error( $output ) ) {
			throw new Exception( $output->get_error_message() );
		}
		return $output;
	}

	/**
	 * Add an image from a URL to the Media Library.
	 * @param string $url The URL of the image to be downloaded.
	 * @param string $filename The filename of the image, if not set, it will be the basename of the URL.
	 * @param string $title The title of the image.
	 * @param string $description The description of the image.
	 * @param string $caption The caption of the image.
	 * @param string $alt The alt text of the image.
	 * @return int The attachment ID of the image.
	 */
	public function add_image_from_url( $url, $filename = null, $title = null, $description = null, $caption = null, $alt = null ) {
		$path_parts = pathinfo( parse_url( $url, PHP_URL_PATH ) );
		$url_filename = $path_parts['basename'];
		$file_type = wp_check_filetype( $url_filename, null );
		$allowed_types = get_allowed_mime_types();
		if ( !$file_type || !in_array( $file_type['type'], $allowed_types ) ) {
			throw new Exception( 'Invalid file type from URL.' );
		}
	
		// Initial extension from URL file name
		$extension = $file_type['ext'];
	
		if ( !empty( $filename ) ) {
			$custom_file_type = wp_check_filetype( $filename, null );
			if ( !$custom_file_type || !in_array( $custom_file_type['type'], $allowed_types ) ) {
				throw new Exception( 'Invalid custom file type.' );
			}
			// Use the extension from the custom filename if valid
			$extension = $custom_file_type['ext'];
		}
	
		$image_data = $this->download_image( $url );
		if ( !$image_data ) {
			throw new Exception( 'Could not download the image.' );
		}
		$upload_dir = wp_upload_dir();
	
		// Filename handling including 'generated_' prefix scenario
		if ( empty( $filename ) ) {
			$filename = sanitize_file_name( $url_filename );
			if ( empty( $extension ) ) { // This condition might now be redundant
				$extension = $file_type['ext'];
			}
			// Filename length check and prepend if conditions met
			if ( strlen( $filename ) > 32 || strlen( $filename ) < 4 || strpos( $filename, 'generated_' ) === 0 ) {
				$filename = $this->get_random_id( 16 ) . '.' . $extension;
			}
			if ( strpos( $filename, '.' ) === false ) {
				$filename .= '.' . $extension;
			}
		}
	
		// Directory and file path handling
		if ( wp_mkdir_p( $upload_dir['path'] ) ) {
			$file = $upload_dir['path'] . '/' . $filename;
		}
		else {
			$file = $upload_dir['basedir'] . '/' . $filename;
		}
		
		// Ensure file name uniqueness in the directory
		$i = 1;
		$parts = pathinfo( $file );
		while ( file_exists( $file ) ) {
			$file = $parts['dirname'] . '/' . $parts['filename'] . '-' . $i . '.' . $parts['extension'];
			$i++;
		}
	
		// Writing the file to disk
		file_put_contents( $file, $image_data );
	
		// Attachment and metadata handling in WP
		$attachment = [
			'post_mime_type' => $file_type['type'],
			'post_title' => $title ?? '',
			'post_content' => $description ?? '',
			'post_excerpt' => $caption ?? '',
			'post_status' => 'inherit'
		];
		$attachmentId = wp_insert_attachment( $attachment, $file );
		require_once( ABSPATH . 'wp-admin/includes/image.php' );
		$attachment_data = wp_generate_attachment_metadata( $attachmentId, $file );
		wp_update_attachment_metadata( $attachmentId, $attachment_data );
		update_post_meta( $attachmentId, '_wp_attachment_image_alt', $alt );
	
		return $attachmentId;
	}	
 	#endregion

	#region Context-Related Helpers
	function retrieve_context( $params, $query ) {
		$contextMaxLength = $params['contextMaxLength'] ?? $this->get_option( 'context_max_length', 4096 );
    $embeddingsEnvId = $params['embeddingsEnvId'] ?? null;
		$context = apply_filters( 'mwai_context_search', [], $query, [
			'embeddingsEnvId' => $embeddingsEnvId
		]);
		if ( empty( $context ) ) {
			return null;
		}
		else if ( !isset( $context['content'] ) ) {
			$this->log( "⚠️ A context without content was returned." );
			return null;
		}
		$context['content'] = $this->clean_sentences( $context['content'], $contextMaxLength );
		$context['length'] = strlen( $context['content'] );
		return $context;
	}
	#endregion

	#region Users/Sessions Helpers

	function get_nonce( $force = false ) {
		if ( !$force && !is_user_logged_in() ) {
			return null;
		}
		if ( isset( $this->nonce ) ) {
			return $this->nonce;
		}
		$this->nonce = wp_create_nonce( 'wp_rest' );
		return $this->nonce;
	}

	function get_session_id() {
		if ( isset( $_COOKIE['mwai_session_id'] ) ) {
			return $_COOKIE['mwai_session_id'];
		}
		return "N/A";
	}

	// Get the UserID from the data, or from the current user
  function get_user_id( $data = null ) {
		// TODO: Not sure if that's the best way, but we should probably use an admin user as a fallback for CRON.
		if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
			$admin = get_users( [ 'role' => 'administrator' ] );
			if ( !empty( $admin ) ) {
				return $admin[0]->ID;
			}
		}
    if ( isset( $data ) && isset( $data['userId'] ) ) {
      return (int)$data['userId'];
    }
    if ( is_user_logged_in() ) {
      $current_user = wp_get_current_user();
      if ( $current_user->ID > 0 ) {
        return $current_user->ID;
      }
    }
    return null;
  }

	function get_admin_user() {
		$admin = get_users( [ 'role' => 'administrator' ] );
		if ( !empty( $admin ) ) {
			return $admin[0];
		}
		return null;
	}

	function get_user_data() {
		$user = wp_get_current_user();
		if ( empty( $user ) || empty( $user->ID ) ) {
			return null;
		}
		$placeholders = array(
			'FIRST_NAME' => get_user_meta( $user->ID, 'first_name', true ),
			'LAST_NAME' => get_user_meta( $user->ID, 'last_name', true ),
			'USER_LOGIN' => isset( $user ) && isset($user->data) && isset( $user->data->user_login ) ? 
				$user->data->user_login : null,
			'DISPLAY_NAME' => isset( $user ) && isset( $user->data ) && isset( $user->data->display_name ) ?
				$user->data->display_name : null,
			'AVATAR_URL' => get_avatar_url( get_current_user_id() ),
		);
		return $placeholders;
	}		

	function get_ip_address( $params = null ) {
		$ip = '127.0.0.1';
		$headers = [
			'HTTP_TRUE_CLIENT_IP',
			'HTTP_CF_CONNECTING_IP',
			'HTTP_X_REAL_IP',
			'HTTP_CLIENT_IP',
			'HTTP_X_FORWARDED_FOR',
			'HTTP_X_FORWARDED',
			'HTTP_X_CLUSTER_CLIENT_IP',
			'HTTP_FORWARDED_FOR',
			'HTTP_FORWARDED',
			'REMOTE_ADDR',
		];
	
		if ( isset( $params ) && isset( $params[ 'ip' ] ) ) {
			$ip = ( string )$params[ 'ip' ];
		} else {
			foreach ( $headers as $header ) {
				if ( array_key_exists( $header, $_SERVER ) && !empty( $_SERVER[ $header ] && $_SERVER[ $header ] != '::1' ) ) {
					$address_chain = explode( ',', wp_unslash( $_SERVER [ $header ] ) );
					$ip = filter_var( trim( $address_chain[ 0 ] ), FILTER_VALIDATE_IP );
					break;
				}
			}
		}
	
		return filter_var( apply_filters( 'mwai_get_ip_address', $ip ), FILTER_VALIDATE_IP );
  	}

	#endregion

	#region Other Helpers

	public function check_rest_nonce( $request ) {
    $nonce = $request->get_header( 'X-WP-Nonce' );
    $rest_nonce = wp_verify_nonce( $nonce, 'wp_rest' );
		return apply_filters( 'mwai_rest_authorized', $rest_nonce, $request );
  }

	function get_random_id( $length = 8, $excludeIds = [] ) {
		$characters = '0123456789abcdefghijklmnopqrstuvwxyz';
		$charactersLength = strlen( $characters );
		$randomId = '';
		for ( $i = 0; $i < $length; $i++ ) {
			$randomId .= $characters[rand( 0, $charactersLength - 1 )];
		}
		if ( in_array( $randomId, $excludeIds ) ) {
			return $this->get_random_id( $length, $excludeIds );
		}
		return $randomId;
	}

	function is_url( $url ) {
		return strpos( $url, 'http' ) === 0 ? true : false;
	}

	function get_post_types() {
		$excluded = array( 'attachment', 'revision', 'nav_menu_item' );
		$post_types = array();
		$types = get_post_types( [], 'objects' );

		// Let's get the Post Types that are enabled for Embeddings Sync
		$embeddingsSettings = $this->get_option( 'embeddings' );
    $syncPostTypes = isset( $embeddingsSettings['syncPostTypes'] ) ? $embeddingsSettings['syncPostTypes'] : [];
		
		foreach ( $types as $type ) {
			$forced = in_array( $type->name, $syncPostTypes );
			// Should not be excluded.
			if ( !$forced && in_array( $type->name, $excluded ) ) {
				continue;
			}
			// Should be public.
			if ( !$forced && !$type->public ) {
				continue;
			}
			$post_types[] = array(
				'name' => $type->labels->name,
				'type' => $type->name,
			);
		}

		// Let's get the Post Types that are enabled for Embeddings Sync
		$embeddingsSettings = $this->get_option( 'embeddings' );
    $syncPostTypes = isset( $embeddingsSettings['syncPostTypes'] ) ? $embeddingsSettings['syncPostTypes'] : [];

		return $post_types;
	}

	function get_post( $post ) {
		if ( is_numeric( $post ) ) {
			$post = get_post( $post );
		}
		if ( is_object( $post ) ) {
			$post = (array)$post;
		}
		if ( !is_array( $post ) ) {
			return null;
		}
		$language = $this->get_post_language( $post['ID'] );
		$content = $this->get_post_content( $post['ID'] );
		$title = $post['post_title'];
		$excerpt = $post['post_excerpt'];
		$url = get_permalink( $post['ID'] );
		$checksum = wp_hash( $content . $title . $url );
		return [
			'postId' => (int)$post['ID'],
			'title' => $title,
			'content' => $content,
			'excerpt' => $excerpt,
			'url' => $url,
			'language' => $language ?? 'english',
			'checksum' => $checksum,
		];
	}
	#endregion

	#region Usage & Costs

	// Quick and dirty token estimation
  // Let's keep this synchronized with Helpers in JS
  static function estimate_tokens( ...$args ): int {
    $text = "";
    foreach ( $args as $arg ) {
			if ( is_array( $arg ) ) {
				foreach ( $arg as $message ) {
					$text .= isset( $message['content']['text'] ) ? $message['content']['text'] : "";
					$text .= isset( $message['content'] ) && is_string( $message['content'] ) ? $message['content'] : "";
				}
			}
			else if ( is_string( $arg ) ) {
				$text .= $arg;
			}
    }
    $averageTokenLength = 4;
    $words = preg_split( '/\s+/', trim( $text ) );
    $tokenCount = 0;
    foreach ( $words as $word ) {
      $tokenCount += ceil( strlen( $word ) / $averageTokenLength );
    }
    return apply_filters( 'mwai_estimate_tokens', $tokenCount, $text );
	}

  public function record_tokens_usage( $model, $in_tokens, $out_tokens = 0, $returned_price = null ) {
    if ( !is_numeric( $in_tokens ) ) {
      throw new Exception( 'AI Engine: in_tokens must be a number.' );
    }
    if ( !is_numeric( $out_tokens ) ) {
      $out_tokens = 0;
    }
    if ( !$model ) {
      throw new Exception( 'AI Engine: model is required.' );
    }
    $usage = $this->get_option( 'ai_models_usage' );
    $month = date( 'Y-m' );
    if ( !isset( $usage[$month] ) ) {
      $usage[$month] = array();
    }
    if ( !isset( $usage[$month][$model] ) ) {
      $usage[$month][$model] = array( 'prompt_tokens' => 0, 'completion_tokens' => 0, 'total_tokens' => 0 );
    }
    $usage[$month][$model]['prompt_tokens'] += $in_tokens;
    $usage[$month][$model]['completion_tokens'] += $out_tokens;
    $usage[$month][$model]['total_tokens'] += $in_tokens + $out_tokens;
    $this->update_option( 'ai_models_usage', $usage );
    $usageInfo = [
      'prompt_tokens' => $in_tokens,
      'completion_tokens' => $out_tokens,
      'total_tokens' => $in_tokens + $out_tokens,
    ];
		if ( $returned_price !== null ) {
			$usageInfo['price'] = $returned_price;
		}
		return $usageInfo;
  }

	public function record_audio_usage( $model, $seconds ) {
		if ( !is_numeric( $seconds ) ) {
			throw new Exception( 'AI Engine: seconds must be a number.' );
		}
		if ( !$model ) {
			throw new Exception( 'AI Engine: model is required.' );
		}
		$usage = $this->get_option( 'ai_models_usage' );
		$month = date( 'Y-m' );
		if ( !isset( $usage[$month] ) ) {
			$usage[$month] = array();
		}
		if ( !isset( $usage[$month][$model] ) ) {
			$usage[$month][$model] = array( 'seconds' => 0 );
		}
		$usage[$month][$model]['seconds'] += $seconds;
		$this->update_option( 'ai_models_usage', $usage );
		return [ 'seconds' => $seconds ];
	}

  public function record_images_usage( $model, $resolution, $images ) {
    if ( !$model || !$resolution || !$images ) {
      throw new Exception( 'Missing parameters for record_image_usage.' );
    }
    $usage = $this->get_option( 'ai_models_usage' );
    $month = date( 'Y-m' );
    if ( !isset( $usage[$month] ) ) {
      $usage[$month] = array();
    }
    if ( !isset( $usage[$month][$model] ) ) {
      $usage[$month][$model] = array( 'resolution' => array(), 'images' => 0 );
    }
    if ( !isset( $usage[$month][$model]['resolution'][$resolution] ) ) {
      $usage[$month][$model]['resolution'][$resolution] = 0;
    }
    $usage[$month][$model]['resolution'][$resolution] += $images;
    $usage[$month][$model]['images'] += $images;
    $this->update_option( 'ai_models_usage', $usage );
    return [ 'resolution' => $resolution, 'images' => $images ];
  }

	#endregion

	#region Streaming
	public function stream_push( $data ) {
		$out = "data: " . json_encode( $data );
		echo $out;
		echo "\n\n";
		if ( ob_get_level() > 0 ) {
			ob_end_flush();
		}
		flush();
	}
	#endregion

	#region Options
	function get_themes() {
		$themes = get_option( $this->themes_option_name, [] );
		$themes = empty( $themes ) ? [] : $themes;

		$internalThemes = [
			'chatgpt' => [
				'type' => 'internal','name' => 'ChatGPT', 'themeId' => 'chatgpt',
				'settings' => [], 'style' => ""
			],
			'messages' => [
				'type' => 'internal', 'name' => 'Messages', 'themeId' => 'messages',
				'settings' => [], 'style' => ""
			],
			'timeless' => [
				'type' => 'internal', 'name' => 'Timeless', 'themeId' => 'timeless',
				'settings' => [], 'style' => ""
			],
		];
		$customThemes = [];
		foreach ( $themes as $theme ) {
			if ( isset( $internalThemes[$theme['themeId']] ) ) {
				$internalThemes[$theme['themeId']] = $theme;
				continue;
			}
			$customThemes[] = $theme;
		}
		return array_merge(array_values($internalThemes), $customThemes);
	}

	function update_themes( $themes ) {
		update_option( $this->themes_option_name, $themes );
		return $themes;
	}

	function get_chatbots() {
		$chatbots = get_option( $this->chatbots_option_name, [] );
		$hasChanges = false;
		if ( empty( $chatbots ) ) {
			$chatbots = [ array_merge( MWAI_CHATBOT_DEFAULT_PARAMS, ['name' => 'Default', 'botId' => 'default' ] ) ];
		}
		$hasDefault = false;
		foreach ( $chatbots as &$chatbot ) {
			if ( $chatbot['botId'] === 'default' ) {
				$hasDefault = true;
			}
			foreach ( MWAI_CHATBOT_DEFAULT_PARAMS as $key => $value ) {
				// Use default value if not set.
				if ( !isset( $chatbot[$key] ) ) {
					$chatbot[$key] = $value;
				}
			}
			// TODO: After October 2024, let's remove this.
			if ( isset( $chatbot['context'] ) ) {
				$chatbot['instructions'] = $chatbot['context'];
				unset( $chatbot['context'] );
				$hasChanges = true;
			}
			// TODO: After October 2024, let's remove this.
			if ( isset( $chatbot['fileUpload'] ) ) {
				$chatbot['fileSearch'] = $chatbot['fileUpload'];
				unset( $chatbot['fileUpload'] );
				$hasChanges = true;
			}
		}
		if ( !$hasDefault ) {
			$defaultBot = array_merge( MWAI_CHATBOT_DEFAULT_PARAMS, ['name' => 'Default', 'botId' => 'default' ] );
			array_unshift( $chatbots, $defaultBot );
			$hasChanges = true;
		}
		if ( $hasChanges ) {
			update_option( $this->chatbots_option_name, $chatbots );
		}
		return $chatbots;
	}

	function get_chatbot( $botId ) {
		$chatbots = $this->get_chatbots();
		foreach ( $chatbots as $chatbot ) {
			if ( $chatbot['botId'] === (string)$botId ) {
				return $chatbot;
			}
		}
		return null;
	}

	function get_embeddings_env( $envId ) {
		$envs = $this->get_option( 'embeddings_envs' );
		foreach ( $envs as $env ) {
			if ( $env['id'] === $envId ) {
				return $env;
			}
		}
		return null;
	}

	function get_ai_env( $envId ) {
		$envs = $this->get_option( 'ai_envs' );
		foreach ( $envs as $env ) {
			if ( $env['id'] === $envId ) {
				return $env;
			}
		}
		return null;
	}

	function get_assistant( $envId, $assistantId ) {
		$env = $this->get_ai_env( $envId );
		if ( !$env ) {
			return null;
		}
		$assistants = $env['assistants'];
		foreach ( $assistants as $assistant ) {
			if ( $assistant['id'] === $assistantId ) {
				return $assistant;
			}
		}
		return null;
	}

	function get_theme( $themeId ) {
		$themes = $this->get_themes();
		foreach ( $themes as $theme ) {
			if ( $theme['themeId'] === $themeId ) {
				return $theme;
			}
		}
		return null;
	}

	function update_chatbots( $chatbots ) {
		$deprecatedFields = [ 'env', 'embeddingsIndex', 'embeddingsNamespace', 'service' ];
		$htmlFields = [ 'textCompliance', 'aiName', 'userName', 'startSentence' ];
		$keepLineReturnsFields = [ 'instructions' ];
		$whiteSpacedFields = [ 'context' ];
		foreach ( $chatbots as &$chatbot ) {
			foreach ( $chatbot as $key => &$value ) {
				if ( in_array( $key, $deprecatedFields ) ) {
					unset( $chatbot[$key] );
					continue;
				}
				if ( in_array( $key, $htmlFields ) ) {
					$value = wp_kses_post( $value );
				}
				else if ( in_array( $key, $whiteSpacedFields ) ) {
					$value = sanitize_textarea_field( $value );
				}
				else if ( $key === 'functions' ) {
					$functions = [];
					foreach ( $value as $function ) {
						if ( isset( $function['id'] ) && isset( $function['type'] ) ) {
							$functions[] = [
								'id' => sanitize_text_field( $function['id'] ),
								'type' => sanitize_text_field( $function['type'] ),
							];
						}
					}
					$value = $functions;
				}
				else {
					if ( in_array( $key, $keepLineReturnsFields ) ) {
						$value = preg_replace( '/\r\n/', "[==LINE_RETURN==]", $value );
						$value = preg_replace( '/\n/', "[==LINE_RETURN==]", $value );
					}
					$value = sanitize_text_field( $value );
					if ( in_array( $key, $keepLineReturnsFields ) ) {
						$value = preg_replace( '/\[==LINE_RETURN==\]/', "\n", $value );
					}
				}
			}
		}
		if ( !update_option( $this->chatbots_option_name, $chatbots ) ) {
			$this->log( '⚠️ Could not update chatbots.' );
			$chatbots = get_option( $this->chatbots_option_name, [] );
			return $chatbots;
		}
		return $chatbots;
	}

	function get_all_options( $force = false ) {
		// We could cache options this way, but if we do, the apply_filters seems to be called too early.
		// That causes issues with the mwai_languages filter.
		// if ( !$force && !is_null( $this->options ) ) {
		// 	return $this->options;
		// }
		$options = get_option( $this->option_name, [] );
		$options = $this->sanitize_options( $options );
		foreach ( MWAI_OPTIONS as $key => $value ) {
			if ( !isset( $options[$key] ) ) {
				$options[$key] = $value;
			}
			if ( $key === 'languages' ) {
				// NOTE: If we decide to make a set of options for languages, we can keep it in the settings
				$options[$key] = apply_filters( 'mwai_languages', MWAI_LANGUAGES );
			}
		}
		$options['chatbot_defaults'] = MWAI_CHATBOT_DEFAULT_PARAMS;
		$options['default_limits'] = MWAI_LIMITS;

		// Consolidate the engines and the models inside them
		// we should ABSOLUTELY AVOID to use ai_models directly (except for saving).
		// An engine looks like that: 
		// [ 'name' => 'Ollama', 'type' => 'ollama', inputs => ['apikey', 'endpoint'], models => [] ]
		// NOTE: Since the models are consolidated with the envId in ai_engines,
 		$options['ai_engines'] = apply_filters( 'mwai_engines', MWAI_ENGINES );
		foreach ( $options['ai_engines'] as &$engine ) {
			if ( $engine['type'] === 'openai' ) {
				$engine['models'] = apply_filters(  'mwai_openai_models',
					Meow_MWAI_Engines_OpenAI::get_models_static()
				);
			}
			else if ( $engine['type'] === 'anthropic' ) {
				$engine['models'] = apply_filters(  'mwai_anthropic_models',
					Meow_MWAI_Engines_Anthropic::get_models_static()
				);
			}
			else {
				$engine['models'] = [];
				foreach ( $options['ai_models'] as $model ) {
					if ( $model['type'] === $engine['type'] ) {
						$engine['models'][] = $model;
					}
				}
			}
		}

		// Support for functions via Snippet Vault
		$options['functions'] = apply_filters( 'mwai_functions_list', [] );

		// Addons
		$options['addons'] = apply_filters( 'mwai_addons', [
			[
				'slug' => "mwai-notifications",
				'name' => "Notifications",
				'icon_url' => MeowCommon_Admin::$logo,
				'description' => "Add-on for AI Engine that adds notifications.",
				'install_url' => "https://meowapps.com/products/mwai-notifications/",
				'settings_url' => null,
				'enabled' => false,
			], [
				'slug' => "mwai-ollama",
				'name' => "Ollama",
				'icon_url' => MeowCommon_Admin::$logo,
				'description' => "Support for local LLMs via Ollama. Select the 'Ollama' type in your 'Environments for AI', then you can 'Refresh Models' and use them!",
				'install_url' => "https://meowapps.com/products/mwai-ollama/",
				'settings_url' => null,
				'enabled' => false
			]
		] );

		//$this->options = $options;
		return $options;
	}

	// Sanitize options when we update the plugi or perform some updates
	// if we change the structure of the options.
	function sanitize_options( $options ) {
		$needs_update = false;

		// TODO: After October 2024, let's remove this.
		$old_options = [
			'openai_models',
			'anthropic_models',
			'${envType}_models',
			'shortcode_chat_params',
			'extra_models',
			'fallback_model',
			'mwai_advisor_data'
		];
		foreach ( $old_options as $old_option ) {
			if ( isset( $options[$old_option] ) ) {
				unset( $options[$old_option] );
				$needs_update = true;
			}
		}

		// TODO: After October 2024, let's remove this.
		#region Temporary Code
		if ( isset( $options['openrouter_models'] ) ) {
			foreach ( $options['openrouter_models'] as $model ) {
				$model['envId'] = null;
				$model['type'] = 'openrouter';
				$options['ai_models'][] = $model;
			}
			$needs_update = true;
			unset( $options['openrouter_models'] );
		}
		if ( isset( $options['google_models'] ) ) {
			foreach ( $options['google_models'] as $model ) {
				$model['envId'] = null;
				$model['type'] = 'google';
				$options['ai_models'][] = $model;
			}
			$needs_update = true;
			unset( $options['google_models'] );
		}
		if ( isset( $options['shortcode_chat_stream'] ) ) {
			$options['ai_streaming'] = $options['shortcode_chat_stream'];
			unset( $options['shortcode_chat_stream'] );
			$needs_update = true;
		}
		if ( isset( $options['shortcode_chat_syntax_highlighting'] ) ) {
			$options['syntax_highlight'] = $options['shortcode_chat_syntax_highlighting'];
			unset( $options['shortcode_chat_syntax_highlighting'] );
			$needs_update = true;
		}
		if ( isset( $options['shortcode_chat_moderation'] ) ) {
			$options['chatbot_moderation'] = $options['shortcode_chat_moderation'];
			unset( $options['shortcode_chat_moderation'] );
			$needs_update = true;
		}
		if ( isset( $options['shortcode_chat_discussions'] ) ) {
			$options['chatbot_discussions'] = $options['shortcode_chat_discussions'];
			unset( $options['shortcode_chat_discussions'] );
			$needs_update = true;
		}
		if ( isset( $options['shortcode_chat_typewriter'] ) ) {
			$options['chatbot_typewriter'] = $options['shortcode_chat_typewriter'];
			unset( $options['shortcode_chat_typewriter'] );
			$needs_update = true;
		}
		if ( isset( $options['shortcode_chat'] ) ) {
			$options['module_chatbots'] = $options['shortcode_chat'];
			unset( $options['shortcode_chat'] );
			$needs_update = true;
		}
		if ( isset( $options['openai_usage'] ) ) {
			$options['ai_models_usage'] = $options['openai_usage'];
			unset( $options['openai_usage'] );
			$needs_update = true;
		}
		#endregion

		// The IDs for the embeddings environments are generated here.
		// TODO: We should handle this more gracefully via an option in the Embeddings Settings.
		$embeddings_default_exists = false;
		if ( isset( $options['embeddings_envs'] ) ) {
			foreach ( $options['embeddings_envs'] as &$env ) {
				if ( !isset( $env['id'] ) ) {
					$env['id'] = $this->get_random_id();
					$needs_update = true;
				}
				if ( $env['id'] === $options['embeddings_default_env'] ) {
					$embeddings_default_exists = true;
				}
			}
		}
		if ( !$embeddings_default_exists ) {
			$options['embeddings_default_env'] = $options['embeddings_envs'][0]['id'] ?? null;
			$needs_update = true;
		}

		// The IDs for the AI environments are generated here.
		$allEnvIds = [];
		$ai_default_exists = false;
		if ( isset( $options['ai_envs'] ) ) {
			foreach ( $options['ai_envs'] as &$env ) {
				if ( !isset( $env['id'] ) ) {
					$env['id'] = $this->get_random_id();
					$needs_update = true;
				}
				if ( $env['id'] === $options['ai_default_env'] ) {
					$ai_default_exists = true;
				}
				$allEnvIds[] = $env['id'];
			}
		}
		if ( !$ai_default_exists ) {
			$options['ai_default_env'] = $options['ai_envs'][0]['id'] ?? null;
			$needs_update = true;
		}

		// All the models with an envId that does not exist anymore are removed.
		if ( isset( $options['ai_models'] ) ) {
			$options['ai_models'] = array_values( array_filter( $options['ai_models'], 
				function( $model ) use ( $allEnvIds, &$needs_update ) {
					if ( isset( $model['envId'] ) && !in_array( $model['envId'], $allEnvIds ) ) {
						$needs_update = true;
						return false;
					}
					return true;
				}
			) );
		}

		if ( $needs_update ) {
			update_option( $this->option_name, $options, false );
		}

		return $options;
	}

	function update_options( $options ) {
		if ( !update_option( $this->option_name, $options, false ) ) {
			return false;
		}
		$options = $this->get_all_options( true );
		return $options;
	}

	function update_option( $option, $value ) {
		$options = $this->get_all_options( true );
		$options[$option] = $value;
		return $this->update_options( $options );
	}

	function get_option( $option, $default = null ) {
		$options = $this->get_all_options();
		return $options[$option] ?? $default;
	}

	function update_ai_env( $env_id, $option, $value ) {
		$options = $this->get_all_options( true );
		foreach ( $options['ai_envs'] as &$env ) {
			if ( $env['id'] === $env_id ) {
				$env[$option] = $value;
				break;
			}
		}
		return $this->update_options( $options );
	}

	function get_engine_models( $engineType ) {
		$engines = $this->get_option( 'ai_engines' );
		foreach ( $engines as $engine ) {
			if ( $engine['type'] === $engineType ) {
				return isset( $engine['models'] ) ? $engine['models'] : [];
			}
		}
		return [];
	}

	function reset_options() {
		delete_option( $this->themes_option_name );
		delete_option( $this->chatbots_option_name );
		delete_option( $this->option_name );
		return $this->get_all_options( true );
	}
	#endregion

	#region Logs

	function get_logs() {
		$log_file_path = $this->get_logs_path();

		if ( !file_exists( $log_file_path ) ) {
			return "Empty log file.";
		}

		$content = file_get_contents( $log_file_path );
		$lines = explode( "\n", $content );
		$lines = array_filter( $lines );
		$lines = array_reverse( $lines );
		$content = implode( "\n", $lines );
		return $content;
	}

	function clear_logs() {
		$logPath = $this->get_logs_path();
		if ( file_exists( $logPath ) ) {
			unlink( $logPath );
		}

		$options = $this->get_all_options();
		$options['logs_path'] = null;
		$this->update_options( $options );
	}

	function get_logs_path() {
		$uploads_dir = wp_upload_dir();
		$uploads_dir_path = trailingslashit( $uploads_dir['basedir'] );

		$path = $this->get_option( 'logs_path' );

		if ( $path && file_exists( $path ) ) {
			// make sure the path is legal (within the uploads directory with the MWAI_PREFIX and log extension)
			if ( strpos( $path, $uploads_dir_path ) !== 0 || strpos( $path, MWAI_PREFIX ) === false || substr( $path, -4 ) !== '.log' ) {
				$path = null;
			} else {
				return $path;
			}
		}

		if ( !$path ) {
			$path = $uploads_dir_path . MWAI_PREFIX . "_" . $this->random_ascii_chars() . ".log";
			if ( !file_exists( $path ) ) {
				touch( $path );
			}
			$options = $this->get_all_options();
			$options['logs_path'] = $path;
			$this->update_options( $options );
		}

		return $path;
	}

	function log( $data = null ) {
		if ( !$this->get_option( 'server_debug_mode', false ) ) { return false; }
		$log_file_path = $this->get_logs_path();
		$fh = @fopen( $log_file_path, 'a' );
		if ( !$fh ) { return false; }
		$date = date( "Y-m-d H:i:s" );
		if ( is_null( $data ) ) {
			fwrite( $fh, "\n" );
		}
		else {
			fwrite( $fh, "$date: {$data}\n" );
			//error_log( "[MWAI] $data" );
		}
		fclose( $fh );
		return true;
	}

	private function random_ascii_chars( $length = 8 ) {
		$characters = array_merge( range( 'A', 'Z' ), range( 'a', 'z' ), range( '0', '9' ) );
		$characters_length = count( $characters );
		$random_string = '';

		for ( $i = 0; $i < $length; $i++ ) {
			$random_string .= $characters[rand(0, $characters_length - 1)];
		}

		return $random_string;
	}

	#endregion
}

?>

FADUS Healthcare – Affy Pharma Pvt Ltd

SEFOX

POWDER FOR ORAL SUSPENSION
30ML (HDPE BOTTLE)

Composition

Cefpodoxime 50mg/5ml

Indications & Uses

UTIs, LRTs

SYREGO – CV

POWDER FOR ORAL SUSPENSION
30ML (GLASS BOTTLE)

Composition

Cefpodoxime 50mg + Potassium Clavulanate 31.25mg/ 5ml

Indications & Uses

Upper & lower respiratory infections, Uncomplicated skin infections, Urinary Tract Infections

PEMOX-CLAV

POWDER FOR ORAL SUSPENSION
30ML (GLASS +HDPE BOTTLE)

Composition

Amoxycillin 200mg + Potassium clavulanate 28.50 mg/ 5ml

Indications & Uses

Community Acquired Pneumonia, Acute Exacerbations of Chronic Bronchitis, Upper Respiratory Tract Infections, Urinary Tract Infections

CEFIDUS CV

POWDER FOR ORAL SUSPENSION
30ML (GLASS BOTTLE)

Composition

Cefixime 50mg + Potassium clavulanate 31.25mg/5ml

Indications & Uses

Urinary Tract Inefctions, AECB, Otitis Media, Typhoid/p>

CEFIDUS

POWDER FOR ORAL SUSPENSION
30ML (HDPE BOTTLE)

Composition

Cefixime 50mg/5ml

Indications & Uses

Urinary Tract Inefctions, Gastroenteritis

SAMTHRO

ORAL SUSPENSION
15 ml

Composition

Azithromycin 200mg/5ml

Indications & Uses

Community Acquired Pneumonia, Acute Exacerbations of Chronic Bronchitis,

PARADUS-DS

ORAL SUSPENSION
60 ml

Composition

Paracetamol 250mg/5ml

Indications & Uses

Fever, Pain

FADSPAS-M

ORAL SUSPENSION
60 ml

Composition

Paracetamol 125mg + Mefenamic Acid 50mg/5ml

Indications & Uses

Pain, Fever

FADOFLOX

ORAL SUSPENSION
30 ml

Composition

Ofloxacin 50mg/5ml

Indications & Uses

Acute exacerbations of chronic Bronchitis, Diarrhoea

CUFFAD

SYRUP
60 ml

Composition

Paracetamol 125mg + PPH 5mg + Cetirizine HCI 2mg/5ml

Indications & Uses

Fever, common cold & Flu

FAD-HUNGRY

ORAL SUSPENSION
200ml

Composition

Cyproheptadine HCI 2mg + Tricholine citrate 0.275mg/5ml

Indications & Uses

Stimulate Apetite, Induces Weight Gain, Cure Allergies

APRAZ-DSR

CAPSULES ( HARD GELATIN)
10X10 (Alu-Alu)

Composition

Pantoprazole 40mg (EC) + Domperidone 30mg (SR)

Indications & Uses

GERD, Dyspepsia, Acid Peptic Disorders, Gastritis

TAPEN-DSR

CAPSULES ( HARD GELATIN)
11X10 (Alu-Alu)

Composition

Rabeprazole 20mg (EC) + Domperidone SR

Indications & Uses

GERD, Dyspepsia, Acid Peptic Disorders, Gastritis

APRAZ-40

INJECTION
40ml

Composition

Pantoprazole Sodium 40mg + NaCL

Indications & Uses

Acid-peptic disorders in hospitalized patients, Zollinger – Ellison Syndrome, Treatment of GERD Associated with Erasive Esophagitis, GL Bleed

NTICID

SUSPENSION
170ml

Composition

Activated Dimethicone 25mg + Magnesium Hydroxide 200mg+ Aluminium Hydroxide Gel 200mg/10ml

Indications & Uses

Heartburn, Acid Indigestion

FAD-ZYME

SYRUP
200ml

Composition

Alpha Amylase (1:2000) 50mg, Pepsin(1:3000) 10mg/5ml

Indications & Uses

Dyspepsia, Flatulence, Anorexia, Pancreatic Insufficiency

CAROFE

CAPSULES (HARD GELATIN)
10X3X10

Composition

Vitamin C 75mg + Vitamin B12 5mcg + Carbonyl Iron 100mg + Folic Acid 1.5mg + Zinc Sulphate 61.8mg

Indications & Uses

Hyphocromic Anemia in Pregnancy, Chronic and / or Acute Blood Loss, Post-gynaesurgery, Iron Deficiency Anemia

FA-D3 60K

CAPSULES (SOFT GELATIN)
10X1X4

Composition

Cholecalciferol 60000 UI

Indications & Uses

Osteoporosis, Osteoarthritis, Musculoskeletal Pain, Type- 2 Diabetes, Menstrual Irregularities, Pre-eclampsia, IUGR

CALERA

CAPSULES (SOFT GELATIN)
5X2X15

Composition

Calcitriol 0.25mcg + Calcium Carbonate 500mg + Zinc Sulphate 7.5mg

Indications & Uses

Osteoporosis, Hypoparathyroidism, Pregnancy & Lactation, Premenstrual Syndrome

IROFAD

SYRUP (IRON TONIC)
300 ml

Composition

Iron (III) Hydroxide Polymaltose 50mg, Folic Acid 0.5mg/15ml

Indications & Uses

Pregnancy and lactation, Iron Deficiency Anaemia, Anaemia due to Excessive Haemorrhage, Anaemia Associated with Infections and Malignant Disease

FAD-CCD

ORAL SUSPENSION
200ml

Composition

Calcium Carbonate 625mg, Vitamin D3 125 IU/5ml

Indications & Uses

Osteomalacia, Osteoporosis, Fractures, Premenstrual Syndrome

FADSPAS-M

TABLETS
20X10

Composition

Mefenamic Acid 250mg + Dicyclomine HCI 10mg

Indications & Uses

Dysmenorrhea, Irritable Bowel Syndrome, Colic and Bladder Spasm, Abdominal Pain

FADACIT

TABLETS (BLISTERS)
20X10

Composition

Nimeulide 100mg + Paracetamo; 325mg

Indications & Uses

Arthritis Pain, Soft Tissue Trauma Including Sprains, Musculoskeletal Pain, Pain Following Dental Extraction

PARA – T – FORTE

TABLETS

20X10

Composition

Tramadol 37.5mg + Paracetamol 325mg

Indications & Uses

Chronic Back Pain, Osteoarthritis, Postoperative Pain

FASFO

GEL
30g

Composition

Diclofenac Diethylamine 1.16% w/w + Oleum Linseed Oil 3 % w/w + Menthol 5% w/w +Methyl Salicylate 10% w/w

Indications & Uses

Sprains & Strains, Lower Back Pain, Joint Pain, Knee Pain

FAD-SOFT

CREAM
20g

Composition

Urea 10% +Lactic Acid 10% + Propylene Glycol 10% + Liquid Paraffin 10%

Indications & Uses

Foot Cracks, Keratolytic

CLOTIREL

OINTMENT
15g

Composition

Clotrimazole 1% w/w + Beclomethasone Dipropionate 0.025% w/w + Neomycin 0.5% w/w

Indications & Uses

Eczema, Psoriasis, Corticosteroid Responsive Dermatoses

KETOFAD

LOTION
100 ml

Composition

Ketoconazole 2% w/v

Indications & Uses

Pityriasis, Dandruff

KETOFAD-Z

LOTION
100 ml

Composition

Ketoconazole Shampoo 2% w/v + ZPTO 1% w/v

Indications & Uses

Pityriasis, Dandruff

DANDNIL

SOAP
75g

Composition

Ketoconazole 1% w/w

Indications & Uses

Tinea Versicolor, Prophylaxis of Pityriasis Versicolor

FADFLU

TABLETS
20X1X1

Composition

Fluconazole 200mg

Indications & Uses

Vaginal Candidiasis, Brochopulmonary Infections, Candiduria, Tinea Pedis, Corposis, Cruris, Versicolor

FADVIT

SYRUP
200ml

Composition

L-Iysine HCI 25mg + Vitamin B1 2.5mg + Vitamin B2 2.5mg + Vitamin B6 0.75mg + D-panthenol 3mg +Niacinamide 25mg + Mecobalamin 2mcg/10ml

Indications & Uses

Sub-optimal Growth, Poor Weight Gain, Malnutrition, Prolonged Illness

LYCODUS GOLD

SYRUP
225ml

Composition

Each 10ml Contains: Lycopene 6% 1000mcg + Vitamin A Palmitate 2500 IU + Vitamin E 10 IU + Ascorbic Acid 50mg + Selenium (as Sodium Selenate) 35mcg + Zinc (As Zinc Gluconate) 3mg + Manganese (as Manganese Gluconate) 2mg + Iodine ( As Potassium Iodine) 100mcg + Copper (As Copper Sulphate0 500mcg + Thiamine HCI 2mg + Riboflavine 3mg + Pyridoxine HCI 1.5mg

Indications & Uses

Tiredness, Stress, Feeling of Weakness, Vitality Deficiency

VITERA

CAPSULES (SOFT GELATIN)
10X1X10

Composition

Antioxidant, Multivitamin & Multiminerals

Indications & Uses

Tiredness, Stress, Feeling of Weakness, Vitality Deficiency

EWHEA

CAPSULES (SOFT GELATIN)
10X1X10

Composition

Vitamin E (Natural) 400 IU + Wheat Germ Oil 100mg + Omega 3 Fatty Acids 30mg

Indications & Uses

Ulcerative colitis, Metabolic Syndrome, Rheumatoid Arthritis, Type-2 Diabetes, Cardiovascular Diseases

VITERA-4G

CAPSULES (SOFT GELATIN)
10X1X10

Composition

Omega 3 Fatty Acid + Ginseng Extract + Ginkgo Bilaba Extract + Grape Seed Extract + Ginseng Extract + Multimineral + Multivitamin + Antioxidants + Trace Elements

Indications & Uses

Tiredness, Stress, Feeling of Weakness, Vitality Deficiency

VITERA-G

CAPSULES (SOFT GELATIN)
10X1X10

Composition

Ginseng + Multivitamin + Multimineral

Indications & Uses

Tiredness, Stress, Feeling of Weakness, Vitality Deficiency

LYCODUS

CAPSULES (SOFT GELATIN)
10X1X10

Composition

Each SG Contains Lycopene 6% 2000 IU + Vitamin A 2500 IU + Vitamin E Acetate 10 IU + Vitamin C 50 mg + Zinc sulphate Monohydrate 27.45mg + Selenium Dioxide 70mcg

Indications & Uses

Idiopathic Male Infertility, Pre-eclampsia, Prostate Cancer, Cardiovascular Diseases, Diabetes Mellitus

CEFIDUS-200-LB

TABLETS (Alu-Alu)
20X10

Composition

Cefixime 200mg + Lactic Acid Bacilus 2.5 billion spores

Indications & Uses

Otitis Media, Pharyngitis & Tonsillitis, Uncomplicated Urinary Tract Infections, Acute Exacerbations of Chronic Bronchitis, Enteric Fever

CEFIDUS-CV 325

TABLETS (Alu-Alu)
10X1X6

Composition

Cefixime 200mg + Potassium Clavulanate 125mg

Indications & Uses

Respiratory Tract Infections, Urinary Tract Infections, Skin & Skin Structure Infections

PEMOX-CLAV 625

TABLETS (Alu-Alu)
10X1X7

Composition

Amoxycillin 500mg + Potassium Clavulanate 125mg

Indications & Uses

Respiratory Tract Infections, Community Acquired Pneumonia, Gynaecological Infections, Acute Exacerbations of Chronic Bronchitis, Skin and Soft Tissue Infections

FADFLOX-O

TABLETS (Blister)
20X10

Composition

Ofloxacin 200mg + Ornidazole 500mg

Indications & Uses

Surgical ions, Diarrheas of Mixed Etiology, Gynaecological Infections, Orofacial and Dental Infections

LEVOXA-500

TABLETS
10X10

Composition

Levofloxacin 500mg

Indications & Uses

Acute Bacterial Sinusitis, Acute Bacterial Exacerbations of Chronic Bronchitis, Skin & Skin Structure Infections, Chronic Bacterial Prostatitis, Urinary Tract Infections

CEFIDUS-O

TABLETS (Alu-Alu)
20X10

Composition

Cefixime 200mg + Ofloxacin 200mg

Indications & Uses

Community Acquired Pneumonia, Multiple Drug Resistant-TB, Typhoid

FADFLOX

TABLETS (Alu-Alu)
10X1X10

Composition

Cefixime 200mg + Ofloxacin 200mg

Indications & Uses

RTIs, Otitis Media, Sinustis, UTIs, Typhoid

PEMOX-CLAV 1.2

INJECTIONS
1.2g

Composition

Amoxycillin 1000mg + Potassium Clavulanate 200mg + WFI

Indications & Uses

Community Acquired Pneumonia, Gynaecological Infections, Upper Respiratory Tract Infections, Skin and Soft Tissue Infections, Urinary Tract Infections, Acute Exacerbations of Chronic Bronchitis

EFTRI-S 1.5

INJECTIONS
1.5g

Composition

Ceftriaxone 1000mg + Sulbactam 500mg + WFI

Indications & Uses

Gynaecological Infections, Lower Respiratory Tract Infections, Intra-abdominal Infections with Aerobic Organisms, Surgical Prophylaxis

CEFOPER-S 1.5

INJECTIONS
1.5gm

Composition

Cefaperazone 1000mg + Sulbactam 500mg +WFI

Indications & Uses

Peritonitis, Bacterial Simusitis, Cholecystitis, Meningitis

BEMRO

INJECTIONS
1gm

Composition

Meropenem 1gm + WFI

Indications & Uses

Complicated Intra-abdominal Infection (cIAI), Complicated Skin & Skin Structure Infections (cSSSI), Bacterial Meningitis, Noscocomial Pneumonia

PIPDUS-T-4.5

INJECTIONS
4.5gm

Composition

Piperacillin 4000mg + Tazobactam 500mg + WFI

Indications & Uses

Intra-abdominal Infections, Complicated Urinary Tract Infections, Febrile Neutropenia, Lower Respiratory Tract Infections

EFTRI-T 1.125

INJECTIONS
1.125gm

Composition

Ceftriaxone 1000mg + Tazobactam 500 mg + WFI

Indications & Uses

Bone & Joint Infections, Intra-abdominal Infections, Bacterial Meningitis, Pre-operative Surgical Prophylaxis

SEFOX-200

TABLETS (Alu-Alu)
10X1X6

Composition

Cefpodoxime Proxetil 200mg

Indications & Uses

Pharyngitis, CAP, Tonsilitis

BRONKUFF

SYRUP
100ml

Composition

Ambroxol HCI 15mg + Guaiphensin 50mg + Terbutaline Sulphate 1.5mg + Mentholated Base/5ml

Indications & Uses

Bronchitis, Productive Cough, Emphysema, Bronchial Asthma

BRONKUFF-BR

SYRUP
100ml

Composition

Terbutaline Sulphate 2.5mg + Bromhexine HCI 8mg + Guaiphenesin 100mg + Methalated Base/5ml

Indications & Uses

Acute Cough, Abnormal Mucus Secretion, Productive Cough

CUFEX-CP

SYRUP
100ml

Composition

Dextromethorphan Hydrobromide 10mg + Phenylpherine 5 mg + Cetrizine 5mg + Mentholated Base/5ml

Indications & Uses

Commom Cold and Flu, Nasal Congestion, Sore Throat

MONLEV

TABLETS (Alu-Alu)
20X10

Composition

Levocetirizine 5mg + Montelukast 10mg

Indications & Uses

Allergic Rhinitis, Nasal Congestion, Asthma

LOVOFAD

TABLETS (Alu-Alu)
20X11

Composition

Levocetirizine 5mg

Indications & Uses

Chronic Idiopathic Urticaria (CIU), Seasonal Allergic Rhinitis (SAR), Perennial Allergic Rhinitis (PAR)

Arrange A Callback
[]
1 Step 1
Full Name
Telephone
Departmentyour full name
Postal Address
Message
0 /
Previous
Next
Shopping Basket