using System; using System.Collections.Generic; using System.IO; using System.Net.Http; using System.Net.Http.Headers; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading.Tasks; using static AiAgent.Core.Helpers.GenericHelper; using static AiAgent.Core.Constant.ProgramConstants; // "https://api.freepik.com/v1/ai/text-to-image"; // "https://api.freepik.com/v1/ai/text-to-image/flux-dev"; //"https://api.freepik.com/v1/ai/mystic"; namespace AiAgent.Core.Infrastructure; public class FreepikApiClient { // The base URL for the Freepik Mystic API private readonly string _ApiUrl; private readonly HttpClient _httpClient; private readonly string _apiKey; public static async Task GenerateImage(string prompt, string model, string filename) { Log($"- Generating an image with Freepik using model {model}:\n{prompt}"); string apiKey = "FPSX57480408af3186ef6784ddf0587fa562"; var client = new FreepikApiClient(apiKey, model); var responseData = await client.GenerateImageAsync(prompt, filename); return responseData; } /// /// Initializes a new instance of the FreepikApiClient. /// /// Your Freepik API key. public FreepikApiClient(string apiKey, string model) { if (string.IsNullOrWhiteSpace(apiKey)) { throw new ArgumentException("API key cannot be null or whitespace.", nameof(apiKey)); } _ApiUrl = $"https://api.freepik.com/v1/ai/{model}"; _apiKey = apiKey; _httpClient = new HttpClient(); Log($"URL Used: {_ApiUrl}"); } /// /// Generates an image by creating a task and polling for its completion. /// /// The text prompt to generate the image from. /// A MysticApiResponse object containing the generated image data, or null if an error occurs. public async Task GenerateImageAsync(string prompt, string filePath) { try { // 1. Create the task Log($"Creating the task..."); var creationResponse = await CreateGenerationTaskAsync(prompt); var taskId = creationResponse?.Data?.TaskId; if (string.IsNullOrEmpty(taskId)) { Log("Failed to create image generation task."); return Results.Failed; } Log($"Task created with ID: {taskId}. Polling for result..."); // 2. Poll for the result while (true) { await Task.Delay(5000); // Wait for 5 seconds before checking status var statusResponse = await GetTaskStatusAsync(taskId); var status = statusResponse?.Data?.Status?.ToUpper(); Log($" Current task status: {status ?? "UNKNOWN"}"); if (status == "COMPLETED") { //int index = 0; foreach (var imageUrl in statusResponse.Data.Generated) { byte[] imageBytes = await _httpClient.GetByteArrayAsync(imageUrl); //string filename = $"{filePath}-{index}.jpg"; await File.WriteAllBytesAsync(filePath, imageBytes); Log($"Image successfully saved to: {filePath}"); //index++; } return Results.Success; } if (status == "FAILED" || status == "CANCELLED") { Log("Image generation task failed or was cancelled."); return Results.Failed; } // If status is CREATED, PENDING, or IN_PROGRESS, the loop will continue. } } catch (Exception e) { Log($"An unexpected error occurred: {e.Message}"); return Results.Failed; } } /// /// Sends the initial POST request to create an image generation task. /// private async Task CreateGenerationTaskAsync(string prompt) { var requestPayload = new MysticApiRequest { Prompt = prompt }; var jsonPayload = JsonSerializer.Serialize(requestPayload); var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); var request = new HttpRequestMessage(HttpMethod.Post, _ApiUrl); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); request.Headers.Add("X-Freepik-API-Key", _apiKey); request.Content = content; HttpResponseMessage response = await _httpClient.SendAsync(request); var responseBody = await response.Content.ReadAsStringAsync(); //Console.WriteLine($"Create Task Response: {responseBody}"); File.WriteAllText($"Output\\response.json", responseBody); if (response.IsSuccessStatusCode) { return JsonSerializer.Deserialize(responseBody); } Log($"Error creating task: {response.StatusCode}"); Log($"Response: {responseBody}"); return null; } /// /// Sends a GET request to check the status of a generation task. /// private async Task GetTaskStatusAsync(string taskId) { var requestUrl = $"{_ApiUrl}/{taskId}"; var request = new HttpRequestMessage(HttpMethod.Get, requestUrl); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); request.Headers.Add("X-Freepik-API-Key", _apiKey); HttpResponseMessage response = await _httpClient.SendAsync(request); var responseBody = await response.Content.ReadAsStringAsync(); if (response.IsSuccessStatusCode) { return JsonSerializer.Deserialize(responseBody); } Log($"Error getting task status: {response.StatusCode}"); Log($"Response: {responseBody}"); return null; } /// /// Downloads an image from a URL and saves it to a local file. /// /// The URL of the image to download. /// The path where the image will be saved. public async Task DownloadImageAsync(string imageUrl, string filePath) { if (string.IsNullOrEmpty(imageUrl)) { Log($"Failed to download image. URL is null or empty."); return; } try { byte[] imageBytes = await _httpClient.GetByteArrayAsync(imageUrl); await File.WriteAllBytesAsync(filePath, imageBytes); Log($"Image successfully saved to: {filePath}"); } catch (Exception ex) { Log($"Failed to download or save image. Error: {ex.Message}"); } } } // C# classes to model the JSON request and response bodies /// /// Represents the request payload for the Mystic API. /// public class MysticApiRequest { [JsonPropertyName("prompt")] public string Prompt { get; set; } = string.Empty; } /// /// Represents the top-level response from the Mystic API. /// public class MysticApiResponse { [JsonPropertyName("data")] public MysticData? Data { get; set; } } /// /// Represents the data object within the API response, containing task and image info. /// public class MysticData { [JsonPropertyName("task_id")] public string? TaskId { get; set; } [JsonPropertyName("status")] public string? Status { get; set; } [JsonPropertyName("generated")] public List? Generated { get; set; } }