SeemGen/Components/Pages/MainPageBase.cs

360 lines
13 KiB
C#

using BLAIzor.Models;
using BLAIzor.Services;
using Google.Cloud.Speech.V1;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Mvc;
using Microsoft.JSInterop;
using Radzen;
using System.Collections.Concurrent;
using System.Text;
using System.Text.Json;
namespace BLAIzor.Components.Pages
{
public class MainPageBase : ComponentBase
{
public string SelectedBrandName = "default";
[Inject] protected ScopedContentService _scopedContentService { get; set; }
[Inject] protected ContentEditorService _contentEditorService { get; set; }
[Inject] protected IConfiguration configuration { get; set; }
[Inject] protected HttpClient Http { get; set; }
[Inject] protected IJSRuntime jsRuntime { get; set; }
[Inject] protected ISimpleLogger _logger { get; set; }
[Inject] protected AIService ChatGptService { get; set; }
[Inject] protected NotificationService NotificationService { get; set; }
[Inject] protected CacheService CacheService { get; set; }
public static readonly ConcurrentDictionary<string, MainPageBase> _instances = new();
public string SessionId;
public int SiteId;
public SiteInfo SiteInfo;
public StringBuilder HtmlContent = new StringBuilder("");
public string TextContent = "";
public string StatusContent = "";
public string UserInput = string.Empty;
public string TemplateCollectionName = "html_snippets";
public string ContentCollectionName = "";
public bool VoiceEnabled;
public bool TTSEnabled;
public bool STTEnabled;
public bool _initVoicePending = false;
public bool welcomeStage = true;
public bool AiVoicePermitted = true;
public string FirstColumnClass = "";
public bool isEmailFormVisible = false;
public ContactFormModel ContactFormModel = new();
// private string? SuccessMessage;
// private string? ErrorMessage;
public string? DocumentEmailAddress = "";
public string Menu;
public List<MenuItem> MenuItems = new();
public string dynamicallyLoadedCss = string.Empty;
public MenuItem currentMenuItem = new();
public bool IsContentSaved = false;
public WebsiteContentModel SiteModel = new();
public void DoSharedWork()
{
// Logic here
}
public void HandleBrandNameChanged()
{
SelectedBrandName = _scopedContentService.SelectedBrandName;
try
{
StateHasChanged();
}
catch (Exception ex)
{
_ = _logger.ErrorAsync("HandleBrandNameChanged failed", ex.Message);
}
}
public async Task<string> GetMenuList(int siteId)
{
List<MenuItem> 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;
}
public async Task<List<MenuItem>> GetMenuItems(int siteId)
{
List<MenuItem> menuItems = (await _contentEditorService.GetMenuItemsBySiteIdWithChildrenAsync(siteId)).Where(m => m.ShowInMainMenu == true).OrderBy(m => m.SortOrder).ToList();
return menuItems;
}
private string GetApiKey() =>
configuration?.GetSection("ElevenLabsAPI")?.GetValue<string>("ApiKey") ?? string.Empty;
public async Task ConvertTextToSpeech(string textContent)
{
// 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.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}");
}
}
[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);
}
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);
}
public async Task HandleVoiceCommand(string input, string sessionId)
{
// HtmlContent = string.Empty;
UserInput = input;
await InvokeAsync(StateHasChanged);
await SendUserQuery();
//UserInput = string.Empty;
}
public async Task SendUserQuery()
{
welcomeStage = false;
if (!string.IsNullOrEmpty(UserInput))
{
HtmlContent.Clear();
var menu = await GetMenuList(SiteId);
await ChatGptService.ProcessUserIntent(SessionId, UserInput, SiteId, (int)SiteInfo.TemplateId!, TemplateCollectionName, menu);
UserInput = string.Empty;
}
}
public virtual async Task DisplayMenuContent(string input, bool forceUnmodified)
{
welcomeStage = false;
if (!string.IsNullOrEmpty(UserInput))
{
HtmlContent.Clear();
var menu = await GetMenuList(SiteId);
var menuList = await GetMenuItems(SiteId);
var menuItem = CompareMenuItemNames(input, menuList);
if (menuItem == null)
{
await ChatGptService.ProcessContentRequest(SessionId, input, SiteId, (int)SiteInfo.TemplateId!, ContentCollectionName, menu, forceUnmodified);
}
else
{
currentMenuItem = menuItem;
if (!string.IsNullOrEmpty(menuItem.StoredHtml))
{
HtmlContent.Clear();
HtmlContent.Append(menuItem.StoredHtml);
if (currentMenuItem.ContentItemId != null) {
var content = await _contentEditorService.GetContentItemByIdAsync((int)currentMenuItem.ContentItemId);
if (content != null)
{
string removedNumbers = TextHelper.ReplaceNumbersAndSpecialCharacters(content.Content, _scopedContentService.SelectedLanguage);
Console.WriteLine(removedNumbers);
UpdateTextContentForVoice(SessionId, removedNumbers);
}
}
IsContentSaved = true;
}
else
{
await ChatGptService.ProcessContentRequest(SessionId, menuItem, SiteId, (int)SiteInfo.TemplateId!, ContentCollectionName, menu, forceUnmodified);
}
}
UserInput = string.Empty;
}
}
protected async void UpdateTextContentForVoice(string receivedSessionId, string content)
{
if (receivedSessionId != SessionId) return;
TextContent = content;
try
{
await ConvertTextToSpeech(content);
}
catch (Exception ex)
{
await _logger.ErrorAsync("UpdateTextContentForVoice failed", ex.Message);
}
}
public async Task DisplayEmailForm(string emailAddress)
{
FirstColumnClass = "col-12 col-md-6";
DocumentEmailAddress = emailAddress;
isEmailFormVisible = true;
StateHasChanged();
var result = await jsRuntime.InvokeAsync<object>("getDivContent", "currentContent");
_scopedContentService.CurrentDOM = JsonSerializer.Serialize(result);
// Console.Write($"{_scopedContentService.CurrentDOM}");
}
[JSInvokable("ProcessAudio2")]
public static async Task ProcessAudio2(string base64Audio, string sessionId)
{
if (!_instances.TryGetValue(sessionId, out var instance)) return;
if (!instance.STTEnabled) return;
var languageCode = instance._scopedContentService.SelectedLanguage switch
{
"English" => "en-US",
"German" => "de-DE",
_ => "hu-HU"
};
var credentialsPath = instance.configuration.GetSection("GoogleAPI").GetValue<string>("CredentialsPath");
var speech = new SpeechClientBuilder { CredentialsPath = credentialsPath }.Build();
byte[] audioBytes = Convert.FromBase64String(base64Audio);
instance.HtmlContent.Clear();
var response = await speech.RecognizeAsync(new RecognitionConfig
{
Encoding = RecognitionConfig.Types.AudioEncoding.Mp3,
SampleRateHertz = 48000,
LanguageCode = languageCode
}, RecognitionAudio.FromBytes(audioBytes));
foreach (var result in response.Results)
{
foreach (var alternative in result.Alternatives)
{
await instance.HandleVoiceCommand(alternative.Transcript, sessionId);
}
}
}
[JSInvokable("OpenEmailForm2")]
public static async Task OpenEmailForm2(string emailAddress, string sessionId)
{
if (_instances.TryGetValue(sessionId, out var instance))
{
await instance.DisplayEmailForm(emailAddress);
}
}
public async Task SendMessage()
{
Console.WriteLine("Button clicked!");
var menu = await GetMenuList(SiteId);
HtmlContent.Clear();
await ChatGptService.ProcessUserIntent(SessionId, UserInput, SiteId, (int)SiteInfo.TemplateId!, ContentCollectionName, menu);
UserInput = string.Empty;
}
public MenuItem CompareMenuItemNames(string input, List<MenuItem> menuList)
{
var parent = menuList.FirstOrDefault(ml => ml.Name == input);
if (parent != null)
{
return parent;
}
foreach (var item in menuList)
{
var child = item.Children.FirstOrDefault(ch => ch.Name == input);
if (child != null)
{
return child;
}
}
return null; // or throw, or return a default
}
public void ShowNotification(NotificationMessage message)
{
NotificationService.Notify(message);
}
public async ValueTask DisposeAsync()
{
_instances.TryRemove(SessionId, out _);
_scopedContentService.OnBrandNameChanged -= HandleBrandNameChanged;
ChatGptService.OnTextContentAvailable -= UpdateTextContentForVoice;
}
}
}