@page "/" @page "/menu/{topic?}" @using BLAIzor.Models @using BLAIzor.Services @using BLAIzor.Components.Partials @using Google.Cloud.Speech.V1 @using Microsoft.AspNetCore.Identity.UI.Services @using System.Text @using System.Net @using System.Text.Json @using Sidio.Sitemap.Blazor @inject AIService ChatGptService @rendermode InteractiveServer @inject IJSRuntime jsRuntime; @inject IConfiguration configuration @inject ContentService _contentService @inject ContentEditorService _contentEditorService @inject ScopedContentService _scopedContentService @* @inject IEmailSender _emailService *@ @inject NavigationManager _navigationManager @inject IHttpContextAccessor HttpContextAccessor @inject DesignTemplateService DesignTemplateService @inject CssTemplateService CssTemplateService @inject CssInjectorService CssService @inject HttpClient Http @attribute [Sitemap]
Home @* *@
@*
*@
@{ @if(VoiceEnabled) { if(STTEnabled) { } if(TTSEnabled) { if (!AiVoicePermitted) { } else { } } } }
@* Type anything *@ @*
*@

@{ if (!string.IsNullOrEmpty(HtmlContent.ToString())) {
@((MarkupString)HtmlContent.ToString())
if (isEmailFormVisible) {
} } else {

@StatusContent

} }
@* *@

An error occurred: @ex.Message

Please try again later.

@* You can log the exception here if you want *@ @{ Console.WriteLine($"Error caught by ErrorBoundary: {ex.Message}"); }
@code { [Parameter] public string? topic { get; set; } public static Index myHome; private string? Subdomain; public int SiteId; public SiteInfo SiteInfo; private StringBuilder HtmlContent = new StringBuilder(""); private string TextContent = ""; private string StatusContent = ""; private string UserInput = string.Empty; private string ChatGptResponse = string.Empty; private bool isRecording = false; private string FirstColumnClass = ""; private bool isEmailFormVisible = false; private ContactFormModel ContactFormModel = new(); // private string? SuccessMessage; // private string? ErrorMessage; private string? DocumentEmailAddress = ""; private string selectedBrandName = "default"; private string dynamicallyLoadedCss = string.Empty; private string collectionName = "html_snippets"; private string sessionId; private static readonly Dictionary _instances = new(); private string Menu; private bool VoiceEnabled; private bool TTSEnabled; private bool STTEnabled; private bool _initVoicePending = false; private bool welcomeStage = true; private bool AiVoicePermitted = false; private string GetApiKey() => configuration?.GetSection("ElevenLabsAPI")?.GetValue("ApiKey") ?? string.Empty; private void AllowAIVoice() { AiVoicePermitted = true; } private void MuteAI() { AiVoicePermitted = false; } private async Task ConvertTextToSpeech() { // string plainText = WebUtility.HtmlDecode(HtmlContent.ToString()); if (string.IsNullOrWhiteSpace(TextContent) || VoiceEnabled == false || TTSEnabled == false || welcomeStage || !AiVoicePermitted) return; Console.WriteLine("------------------------------OMGOMGOMG TTS call!!!!-------------"); var requestContent = new { text = TextContent, // model_id = "eleven_multilingual_v2", model_id = "eleven_flash_v2_5", voice_settings = new { stability = 0.5, similarity_boost = 0.75, speed = 1 } }; var requestJson = JsonSerializer.Serialize(requestContent); string voiceId; if(SiteInfo.voiceId != null) { voiceId = SiteInfo.voiceId; } else { voiceId = "rE22Kc7UGoQj4zdHNYvd"; } // string voiceId = "yyPLNYHg3CvjlSdSOdLh"; var httpRequest = new HttpRequestMessage(HttpMethod.Post, $"https://api.elevenlabs.io/v1/text-to-speech/{voiceId}/stream") { Content = new StringContent(requestJson, Encoding.UTF8, "application/json") }; httpRequest.Headers.Add("xi-api-key", GetApiKey()); var response = await Http.SendAsync(httpRequest); if (response.IsSuccessStatusCode) { var audioBytes = await response.Content.ReadAsByteArrayAsync(); var base64Audio = Convert.ToBase64String(audioBytes); var audioDataUrl = $"data:audio/mpeg;base64,{base64Audio}"; await jsRuntime.InvokeVoidAsync("playAudio", audioDataUrl); } else { // Handle error response var errorContent = await response.Content.ReadAsStringAsync(); Console.Error.WriteLine($"Error: {errorContent}"); } } protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { await jsRuntime.InvokeVoidAsync("setSessionId", sessionId); await jsRuntime.InvokeVoidAsync("initHints"); // sessionId = Guid.NewGuid().ToString(); // _instances[sessionId] = this; Console.Write($"\n\n SessionId: {sessionId}\n\n"); // _scopedContentService.OnBrandNameChanged += HandleBrandNameChanged; if (!string.IsNullOrEmpty(_scopedContentService.SelectedBrandName)) { selectedBrandName = _scopedContentService.SelectedBrandName; } else { _scopedContentService.SelectedBrandName = "default"; selectedBrandName = "default"; } Subdomain = HttpContextAccessor.HttpContext?.Items["Subdomain"]?.ToString(); SiteInfo = await _scopedContentService.GetSiteInfoByNameAsync(Subdomain); if (SiteInfo != null && SiteInfo.IsPublished) { SiteId = SiteInfo.Id; _scopedContentService.SelectedBrandName = SiteInfo.SiteName; TTSEnabled = SiteInfo.TTSActive; STTEnabled = SiteInfo.STTActive; } else { SiteId = 1; _scopedContentService.SelectedBrandName = "default"; TTSEnabled = false; STTEnabled = false; } _scopedContentService.SelectedSiteId = SiteId; Console.Write("------------------------"); // Load the CSS template for the selected brand from the database var designTemplate = await DesignTemplateService.GetByIdAsync((int)SiteInfo.TemplateId!); var cssTemplate = await CssTemplateService.GetByDesignTemplateIdAsync((int)SiteInfo.TemplateId); collectionName = designTemplate.QDrandCollectionName; if (cssTemplate != null) { dynamicallyLoadedCss = cssTemplate.CssContent; // Assuming Content holds the CSS string var cssPath = await CssTemplateService.SaveTempCssFileAsync(dynamicallyLoadedCss, sessionId); await jsRuntime.InvokeVoidAsync("seemgen.injectCssFile", cssPath); //await CssService.ApplyCssAsync(dynamicallyLoadedCss); } Console.Write($"------------------------ {SiteInfo.MenuItems}, {SiteId}, {SiteInfo.TemplateId}, {SiteInfo.SiteName}"); Menu = await GetMenuList(); if (string.IsNullOrEmpty(HtmlContent.ToString())) { if(!string.IsNullOrWhiteSpace(topic)) { UserInput = topic; await ChatGptService.ProcessContentRequest(sessionId, UserInput, SiteId, (int)SiteInfo.TemplateId!, collectionName, Menu, true); } else { await ChatGptService.GetChatGptWelcomeMessage(sessionId, SiteId, Menu); } // HtmlContent = await ChatGptService.GetChatGptWelcomeMessage(); // UserInput = "Sumerize for me, what is this website about, and what can I do on this website?"; // await ChatGptService.ProcessUserIntent(sessionId, UserInput, SiteId, (int)SiteInfo.TemplateId!, collectionName, Menu); } UserInput = string.Empty; // await InvokeAsync(StateHasChanged); _initVoicePending = true; } if (_initVoicePending) { Console.WriteLine("PENDING VOICE--------------------------------------------------"); _initVoicePending = false; await jsRuntime.InvokeVoidAsync("initVoiceRecorder", "ProcessAudio2"); } } public async void MenuClick(string menuName) { await CallCSharpMethod2(menuName, sessionId, true); } public void HomeClick() { //ChatGptService.OnContentReceived -= UpdateContent; AIService.OnContentReceived -= UpdateContent; _navigationManager.Refresh(true); } private void CancelEmail() { FirstColumnClass = ""; isEmailFormVisible = false; StateHasChanged(); } public Index() { myHome = this; // Set the static reference to the current instance } [JSInvokable("OpenEmailForm2")] public static async void OpenEmailForm2(string emailAddress) { if (myHome != null) { await myHome.DisplayEmailForm(emailAddress); } Console.Write("openEmail with: " + emailAddress); } public async Task DisplayEmailForm(string emailAddress) { FirstColumnClass = "col-12 col-md-6"; DocumentEmailAddress = emailAddress; isEmailFormVisible = true; StateHasChanged(); var result = await jsRuntime.InvokeAsync("getDivContent", "currentContent"); _scopedContentService.CurrentDOM = JsonSerializer.Serialize(result); // Console.Write($"{_scopedContentService.CurrentDOM}"); } [JSInvokable("CallCSharpMethod2")] public static async Task CallCSharpMethod2(string input, string sessionId, bool forceUnModified = false) { // if (myHome != null) // { // await myHome.HandleJsCall(input, ); // } if (_instances.TryGetValue(sessionId, out var instance)) { await instance.HandleJsCall(input, sessionId, forceUnModified); } Console.Write("Button clicked:" + input); } [JSInvokable("ProcessAudio2")] public static async Task ProcessAudio2(string base64Audio, string sessionId) { Console.Write("audio incoming"); if (myHome != null) { if (myHome.STTEnabled == false) return; Console.WriteLine("STT ENABLED -------------------------------------------------------------------------------"); var languageCode = "hu-HU"; if (myHome._scopedContentService.SelectedLanguage == "Hungarian") { languageCode = "hu-HU"; } else if (myHome._scopedContentService.SelectedLanguage == "English") { languageCode = "en-US"; } else if (myHome._scopedContentService.SelectedLanguage == "German") { languageCode = "de-DE"; } var credentialsPath = myHome.configuration.GetSection("GoogleAPI").GetValue("CredentialsPath"); Console.Write(credentialsPath); var builder = new SpeechClientBuilder { CredentialsPath = credentialsPath }; var speech = builder.Build(); byte[] audioBytes = Convert.FromBase64String(base64Audio); myHome.HtmlContent.Clear(); var response = await speech.RecognizeAsync(new RecognitionConfig { Encoding = RecognitionConfig.Types.AudioEncoding.Mp3, SampleRateHertz = 48000, // Match the actual sample rate LanguageCode = languageCode }, RecognitionAudio.FromBytes(audioBytes)); Console.Write("BILLED: " + response.TotalBilledTime); foreach (var result in response.Results) { //Console.Write("RESULT: " + result.Alternatives.Count); foreach (var alternative in result.Alternatives) { //Console.WriteLine($"Transcription: {alternative.Transcript}"); await myHome.HandleVoiceCommand(alternative.Transcript, sessionId); } } } } private async Task SendMessage() { Console.WriteLine("Button clicked!"); var menu = await GetMenuList(); HtmlContent.Clear(); await ChatGptService.ProcessUserIntent(sessionId, UserInput, SiteId, (int)SiteInfo.TemplateId!, collectionName, menu); UserInput = string.Empty; } protected override async Task OnInitializedAsync() { _scopedContentService.OnBrandNameChanged += HandleBrandNameChanged; // ChatGptService.OnContentReceived += UpdateContent; AIService.OnContentReceived += UpdateContent; AIService.OnContentReceiveFinished += UpdateFinished; // ChatGptService.OnStatusChangeReceived += UpdateStatus; AIService.OnStatusChangeReceived += UpdateStatus; AIService.OnTextContentAvailable += UpdateTextContentForVoice; sessionId = Guid.NewGuid().ToString(); _instances[sessionId] = this; VoiceEnabled = configuration?.GetSection("AiSettings")?.GetValue("VoiceActivated") ?? false; } private async void UpdateContent(string receivedSessionId, string content) { if (receivedSessionId == sessionId) // Only accept messages meant for this tab { HtmlContent.Clear(); HtmlContent.Append(content); //InvokeAsync(StateHasChanged); // Ensures UI updates dynamically await InvokeAsync(() => { StateHasChanged(); }); //_scopedContentService.CurrentDOM = await jsRuntime.InvokeAsync("getDivContent", "currentContent"); } } private async void UpdateTextContentForVoice(string receivedSessionId, string content) { if (receivedSessionId == sessionId) // Only accept messages meant for this tab { TextContent = content; await ConvertTextToSpeech(); //_scopedContentService.CurrentDOM = await jsRuntime.InvokeAsync("getDivContent", "currentContent"); } } private async void UpdateFinished(string receivedSessionId) { if (receivedSessionId == sessionId) // Only accept messages meant for this tab { Console.WriteLine("Content update finished"); var result = await jsRuntime.InvokeAsync("getDivContent", "currentContent"); //await ConvertTextToSpeech(); _scopedContentService.CurrentDOM = JsonSerializer.Serialize(result); Console.Write(_scopedContentService.CurrentDOM); } } private async Task ContentChangedInForm() { var result = await jsRuntime.InvokeAsync("getDivContent", "currentContent"); _scopedContentService.CurrentDOM = JsonSerializer.Serialize(result); Console.Write(_scopedContentService.CurrentDOM); } private async void UpdateStatus(string receivedSessionId, string content) { if (receivedSessionId == sessionId) // Only accept messages meant for this tab { StatusContent = content; //InvokeAsync(StateHasChanged); // Ensures UI updates dynamically await InvokeAsync(() => { StateHasChanged(); }); } } public async Task Enter(KeyboardEventArgs e) { if (e.Code == "Enter" || e.Code == "NumpadEnter") { var menu = await GetMenuList(); HtmlContent.Clear(); string input = "Please tell me more about: " + UserInput; await ChatGptService.ProcessUserIntent(sessionId, input, SiteId, (int)SiteInfo.TemplateId!, collectionName, menu); UserInput = string.Empty; } } public async Task HandleVoiceCommand(string input, string sessionId) { // HtmlContent = string.Empty; UserInput = input; await InvokeAsync(StateHasChanged); await SendUserQuery(); //UserInput = string.Empty; } public async Task HandleJsCall(string input, string sessionId, bool forceUnmodified) { HtmlContent.Clear(); await InvokeAsync(StateHasChanged); UserInput = input; await DisplayMenuContent(input, forceUnmodified); UserInput = string.Empty; await InvokeAsync(StateHasChanged); } private async Task SendUserQuery() { welcomeStage = false; if (!string.IsNullOrEmpty(UserInput)) { HtmlContent.Clear(); var menu = await GetMenuList(); await ChatGptService.ProcessUserIntent(sessionId, UserInput, SiteId, (int)SiteInfo.TemplateId!, collectionName, menu); UserInput = string.Empty; } } private async Task DisplayMenuContent(string input, bool forceUnmodified) { welcomeStage = false; if (!string.IsNullOrEmpty(UserInput)) { HtmlContent.Clear(); var menu = await GetMenuList(); var menuItem = (await GetMenuItems()).Where(m => m.Name == input).FirstOrDefault(); if (menuItem == null) { await ChatGptService.ProcessContentRequest(sessionId, input, SiteId, (int)SiteInfo.TemplateId!, collectionName, menu, forceUnmodified); } else { await ChatGptService.ProcessContentRequest(sessionId, menuItem, SiteId, (int)SiteInfo.TemplateId!, collectionName, menu, forceUnmodified); } UserInput = string.Empty; } } private async Task GetMenuList() { List menuItems = (await _contentEditorService.GetMenuItemsBySiteIdAsync(SiteId)).Where(m => m.ShowInMainMenu == true).OrderBy(m => m.SortOrder).ToList(); string menuList = ""; foreach (MenuItem item in menuItems) { menuList += item.Name + ","; } return menuList; } private async Task> GetMenuItems() { List menuItems = (await _contentEditorService.GetMenuItemsBySiteIdAsync(SiteId)).Where(m => m.ShowInMainMenu == true).OrderBy(m => m.SortOrder).ToList(); return menuItems; } private async void HandleBrandNameChanged() { selectedBrandName = _scopedContentService.SelectedBrandName; //StateHasChanged(); await InvokeAsync(() => { StateHasChanged(); }); } public void Dispose() { dynamicallyLoadedCss = ""; HtmlContent.Clear(); _scopedContentService.OnBrandNameChanged -= HandleBrandNameChanged; AIService.OnContentReceived -= UpdateContent; AIService.OnContentReceiveFinished -= UpdateFinished; AIService.OnStatusChangeReceived -= UpdateStatus; AIService.OnTextContentAvailable -= UpdateTextContentForVoice; } public async ValueTask DisposeAsync() { await CssTemplateService.DeleteSessionCssFile(sessionId); } }