1428 lines
46 KiB
C#
1428 lines
46 KiB
C#
using System;
|
|
using System.Linq;
|
|
using xModels.Dtos;
|
|
using System.Threading;
|
|
using xAiModels.Constants;
|
|
using xCommons.Extensions;
|
|
using xAiModels.Extensions;
|
|
using xAiModels.Interfaces;
|
|
using xAiModels.Models.Dtos;
|
|
using xExceptions.Constants;
|
|
using System.Threading.Tasks;
|
|
using xCommons.Configurations;
|
|
using xAiModels.Providers.Hubs;
|
|
using xAiModels.Interfaces.Dtos;
|
|
using xStringService.Interfaces;
|
|
using System.Collections.Generic;
|
|
using Microsoft.AspNetCore.SignalR;
|
|
using xAiModels.Interfaces.Enrichers;
|
|
|
|
namespace xAiModels.Providers
|
|
{
|
|
/// <summary>
|
|
/// All Data Manipulation Requirements ...
|
|
/// </summary>
|
|
public class XAiDataProvider : IXAiDataProvider
|
|
{
|
|
//
|
|
#region Properties ...
|
|
private readonly IXStringProvider stringProvider;
|
|
private readonly XAppConfiguration appConfiguration;
|
|
private readonly IHubContext<XAiDataProviderHub> hub;
|
|
private readonly IXAiMessageEnricher messageEnricher;
|
|
private readonly IXAiProjectEnricher projectEnricher;
|
|
private readonly IXAiConversationEnricher conversationEnricher;
|
|
private readonly IXAiMessageRepositoryService messageRepositoryService;
|
|
private readonly IXAiProjectRepositoryService projectRepositoryService;
|
|
private readonly IXAiProjectTitleResourceProvider projectTitleResourceProvider;
|
|
private readonly IXAiConversationRepositoryService conversationRepositoryService;
|
|
private readonly IXAiConversationTitleResourceProvider conversationTitleResourceProvider;
|
|
private readonly IXAiProjectDescriptionResourceProvider projectDescriptionResourceProvider;
|
|
#endregion
|
|
|
|
public XAiDataProvider(
|
|
IXStringProvider stringProvider,
|
|
XAppConfiguration appConfiguration,
|
|
IHubContext<XAiDataProviderHub> hub,
|
|
IXAiProjectEnricher projectEnricher,
|
|
IXAiMessageEnricher messageEnricher,
|
|
IXAiConversationEnricher conversationEnricher,
|
|
IXAiMessageRepositoryService messageRepositoryService,
|
|
IXAiProjectRepositoryService projectRepositoryService,
|
|
IXAiProjectTitleResourceProvider projectTitleResourceProvider,
|
|
IXAiConversationRepositoryService conversationRepositoryService,
|
|
IXAiConversationTitleResourceProvider conversationTitleResourceProvider,
|
|
IXAiProjectDescriptionResourceProvider projectDescriptionResourceProvider
|
|
)
|
|
{
|
|
this.hub = hub;
|
|
this.stringProvider = stringProvider;
|
|
this.projectEnricher = projectEnricher;
|
|
this.messageEnricher = messageEnricher;
|
|
this.appConfiguration = appConfiguration;
|
|
this.conversationEnricher = conversationEnricher;
|
|
this.messageRepositoryService = messageRepositoryService;
|
|
this.projectRepositoryService = projectRepositoryService;
|
|
this.projectTitleResourceProvider = projectTitleResourceProvider;
|
|
this.conversationRepositoryService = conversationRepositoryService;
|
|
this.conversationTitleResourceProvider = conversationTitleResourceProvider;
|
|
this.projectDescriptionResourceProvider = projectDescriptionResourceProvider;
|
|
}
|
|
|
|
//
|
|
#region Loaders ...
|
|
/// <summary>
|
|
/// Load Projects List of Specified Owner ...
|
|
/// </summary>
|
|
/// <param name="ownerId"></param>
|
|
/// <param name="connectionId"></param>
|
|
/// <param name="fillConversations"></param>
|
|
/// <param name="fillConversationMessages"></param>
|
|
/// <param name="cancellationToken"></param>
|
|
/// <returns></returns>
|
|
public async Task<IEnumerable<XAiProjectDto>> LoadProjects(
|
|
string ownerId,
|
|
string connectionId = null,
|
|
bool fillConversations = false,
|
|
bool fillConversationMessages = false,
|
|
CancellationToken cancellationToken = default
|
|
)
|
|
{
|
|
//
|
|
// Validate Args ...
|
|
if (ownerId.IsNullOrEmpty())
|
|
{
|
|
XException.InvalidArgs.Throw();
|
|
}
|
|
|
|
//
|
|
// Handle Default Project and Conversation ...
|
|
|
|
//
|
|
// Default Project ...
|
|
bool hasDefault = await HasDefaultProject(
|
|
ownerId: ownerId,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
if (!hasDefault)
|
|
{
|
|
//
|
|
await CreateDefaultProject(
|
|
ownerId: ownerId,
|
|
connectionId: connectionId,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
}
|
|
var defaultProject = await GetDefaultProject(
|
|
ownerId: ownerId,
|
|
connectionId: connectionId,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
|
|
//
|
|
// Default Project's Default Conversation ...
|
|
hasDefault = await HasDefaultConversation(
|
|
ownerId: ownerId,
|
|
projectId: defaultProject.Id,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
if (!hasDefault)
|
|
{
|
|
//
|
|
await CreateDefaultConversation(
|
|
ownerId: ownerId,
|
|
connectionId: connectionId,
|
|
projectId: defaultProject.Id,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
}
|
|
|
|
//
|
|
// Retrieve Project List ...
|
|
var result = await projectRepositoryService.FindManyAsync(
|
|
includeBuilder: null,
|
|
ignoreSoftDeleteds: true,
|
|
predicate: x => x.OwnerId == ownerId,
|
|
cancellationToken: cancellationToken,
|
|
orderBuilder: x => x.OrderBy(y => y.CreatedOn)
|
|
);
|
|
|
|
//
|
|
if (result.HasChild())
|
|
{
|
|
//
|
|
result = await projectEnricher.EnrichRange(
|
|
sources: result,
|
|
cancellationToken: cancellationToken,
|
|
fillConversations: fillConversations,
|
|
fillConversationMessages: fillConversationMessages
|
|
);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Load List of Conversations for Specified Project ...
|
|
/// </summary>
|
|
/// <param name="projectId"></param>
|
|
/// <param name="connectionId"></param>
|
|
/// <param name="fillMessages"></param>
|
|
/// <param name="cancellationToken"></param>
|
|
/// <returns></returns>
|
|
public async Task<IEnumerable<XAiConversationDto>> LoadConversations(
|
|
Guid projectId,
|
|
bool fillMessages = false,
|
|
string connectionId = null,
|
|
CancellationToken cancellationToken = default
|
|
)
|
|
{
|
|
//
|
|
// Validate Args ...
|
|
if (projectId.IsNull() ||
|
|
projectId.IsDefaultGuid()
|
|
)
|
|
{
|
|
XException.InvalidArgs.Throw();
|
|
}
|
|
|
|
//
|
|
// Retrieve Project ...
|
|
var project = await projectRepositoryService.GetAsync(
|
|
id: projectId,
|
|
includeBuilder: null,
|
|
ignoreSoftDeleteds: true,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
if (project.IsNullOrDefault())
|
|
{
|
|
XException.NotFound.Throw();
|
|
}
|
|
|
|
//
|
|
// Default Conversation ...
|
|
var hasDefault = await HasDefaultConversation(
|
|
projectId: projectId,
|
|
ownerId: project.OwnerId,
|
|
connectionId: connectionId,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
if (!hasDefault)
|
|
{
|
|
//
|
|
await CreateDefaultConversation(
|
|
projectId: projectId,
|
|
ownerId: project.OwnerId,
|
|
connectionId: connectionId,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
}
|
|
|
|
//
|
|
// Retrieve Conversation's List ...
|
|
var result = await conversationRepositoryService.FindManyAsync(
|
|
includeBuilder: null,
|
|
ignoreSoftDeleteds: false,
|
|
cancellationToken: cancellationToken,
|
|
predicate: x => x.ProjectId == projectId,
|
|
orderBuilder: x => x.OrderBy(y => y.CreatedOn)
|
|
);
|
|
|
|
//
|
|
if (result.HasChild())
|
|
{
|
|
//
|
|
result = await conversationEnricher.EnrichRange(
|
|
sources: result,
|
|
fillMessages: fillMessages,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Load Messages of Specified Conversation ...
|
|
/// </summary>
|
|
/// <param name="conversationId"></param>
|
|
/// <param name="cancellationToken"></param>
|
|
/// <returns></returns>
|
|
public async Task<IEnumerable<XAiMessageDto>> LoadMessages(
|
|
Guid conversationId,
|
|
CancellationToken cancellationToken = default
|
|
)
|
|
{
|
|
//
|
|
// Validate Args ...
|
|
if (conversationId.IsNull() ||
|
|
conversationId.IsDefaultGuid()
|
|
)
|
|
{
|
|
XException.InvalidArgs.Throw();
|
|
}
|
|
|
|
//
|
|
var conversation = await conversationRepositoryService.GetAsync(
|
|
id: conversationId,
|
|
includeBuilder: null,
|
|
ignoreSoftDeleteds: true,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
if (conversation.IsNullOrDefault())
|
|
{
|
|
XException.NotFound.Throw();
|
|
}
|
|
|
|
//
|
|
// Retrieve Message Lists of Specified Conversation ...
|
|
var result = await messageRepositoryService.FindManyAsync(
|
|
includeBuilder: null,
|
|
ignoreSoftDeleteds: true,
|
|
cancellationToken: cancellationToken,
|
|
orderBuilder: x => x.OrderBy(y => y.CreatedOn),
|
|
predicate: x => x.ConversationId == conversationId
|
|
);
|
|
|
|
//
|
|
if (result.HasChild())
|
|
{
|
|
//
|
|
result = await messageEnricher.EnrichRange(
|
|
sources: result,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
#endregion
|
|
|
|
//
|
|
#region Getters ...
|
|
/// <summary>
|
|
/// Retrieve Specified Project ...
|
|
/// </summary>
|
|
/// <param name="id"></param>
|
|
/// <param name="fillConversations"></param>
|
|
/// <param name="fillConversationMessages"></param>
|
|
/// <param name="cancellationToken"></param>
|
|
/// <returns></returns>
|
|
public async Task<XAiProjectDto> GetProject(
|
|
Guid id,
|
|
bool fillConversations = false,
|
|
bool fillConversationMessages = false,
|
|
CancellationToken cancellationToken = default
|
|
)
|
|
{
|
|
//
|
|
// Validate Args ...
|
|
if (id.IsDefaultGuid())
|
|
{
|
|
XException.InvalidArgs.Throw();
|
|
}
|
|
|
|
//
|
|
var result = await projectRepositoryService.GetAsync(
|
|
id: id,
|
|
includeBuilder: null,
|
|
ignoreSoftDeleteds: true,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
if (result.IsNullOrDefault())
|
|
{
|
|
XException.NotFound.Throw();
|
|
}
|
|
|
|
//
|
|
// Handle Enrichment ...
|
|
result = await projectEnricher.Enrich(
|
|
source: result,
|
|
fillConversations: fillConversations,
|
|
cancellationToken: cancellationToken,
|
|
fillConversationMessages: fillConversationMessages
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieve Specified Conversation ...
|
|
/// </summary>
|
|
/// <param name="id"></param>
|
|
/// <param name="fillMessages"></param>
|
|
/// <param name="cancellationToken"></param>
|
|
/// <returns></returns>
|
|
public async Task<XAiConversationDto> GetConversation(
|
|
Guid id,
|
|
bool fillMessages = false,
|
|
CancellationToken cancellationToken = default
|
|
)
|
|
{
|
|
//
|
|
// Validate Args ...
|
|
if (id.IsDefaultGuid())
|
|
{
|
|
XException.InvalidArgs.Throw();
|
|
}
|
|
|
|
//
|
|
var result = await conversationRepositoryService.GetAsync(
|
|
id: id,
|
|
includeBuilder: null,
|
|
ignoreSoftDeleteds: true,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
if (result.IsNullOrDefault())
|
|
{
|
|
XException.NotFound.Throw();
|
|
}
|
|
|
|
//
|
|
// Handle Enrichment ...
|
|
result = await conversationEnricher.Enrich(
|
|
source: result,
|
|
fillMessages: fillMessages,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
#endregion
|
|
|
|
//
|
|
#region Creator/Adders ...
|
|
public async Task<XAiProjectDto> CreateProject(
|
|
string ownerId,
|
|
XAiProjectDto item = null,
|
|
string connectionId = null,
|
|
CancellationToken cancellationToken = default
|
|
)
|
|
{
|
|
//
|
|
// Validate Args ...
|
|
if (ownerId.IsNullOrEmpty())
|
|
{
|
|
XException.InvalidArgs.Throw();
|
|
}
|
|
|
|
//
|
|
// Check Project Provided or not ...
|
|
var hasProject = !item.IsNullOrDefault();
|
|
|
|
//
|
|
// Normalize Provided Project ...
|
|
if (hasProject)
|
|
{
|
|
//
|
|
item.CreatedOn = DateTime.UtcNow;
|
|
|
|
//
|
|
// Validate Item ...
|
|
if (!item.IsValidForAddOrUpdate())
|
|
{
|
|
XException.InvalidData.Throw();
|
|
}
|
|
}
|
|
|
|
//
|
|
XAiProjectDto result = null;
|
|
|
|
//
|
|
// Create Provided Project ...
|
|
if (hasProject)
|
|
{
|
|
//
|
|
result = await projectRepositoryService.AddAsync(
|
|
item: item,
|
|
saveChanges: true,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
|
|
//
|
|
// Handling Send Push Notification ...
|
|
if (!result.IsNullOrDefault() &&
|
|
!connectionId.IsNullOrEmpty()
|
|
)
|
|
{
|
|
//
|
|
await SendPush(
|
|
connectionId: connectionId,
|
|
cancellationToken: cancellationToken,
|
|
payLoad: item.ToJSON(camelCase: true),
|
|
action: XAiDataProviderHubActions.ProjectCreated.GetStringValue()
|
|
);
|
|
}
|
|
}
|
|
//
|
|
// Check Default Project ...
|
|
else
|
|
{
|
|
//
|
|
// Check Default Project Exists or not ...
|
|
var hasDefault = await HasDefaultProject(
|
|
ownerId: ownerId,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
|
|
//
|
|
// If Default Project Exists, Throw Exception ...
|
|
if (hasDefault)
|
|
{
|
|
XException.InvalidArgs.Throw();
|
|
}
|
|
|
|
//
|
|
// Create and Retrive Default Project ...
|
|
result = await GetDefaultProject(
|
|
ownerId: ownerId,
|
|
connectionId: connectionId,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
}
|
|
|
|
//
|
|
// Validate ...
|
|
if (result.IsNullOrDefault())
|
|
{
|
|
XException.ActionFailed.Throw();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
public async Task<XAiConversationDto> CreateConversation(
|
|
Guid projectId,
|
|
XAiConversationDto item = null,
|
|
string connectionId = null,
|
|
CancellationToken cancellationToken = default
|
|
)
|
|
{
|
|
//
|
|
// Validate Args ...
|
|
if (projectId.IsNull() ||
|
|
projectId.IsDefaultGuid())
|
|
{
|
|
XException.InvalidArgs.Throw();
|
|
}
|
|
|
|
//
|
|
// Handle Proejct ...
|
|
XAiProjectDto project = await projectRepositoryService.GetAsync(
|
|
id: projectId,
|
|
includeBuilder: null,
|
|
ignoreSoftDeleteds: true,
|
|
// fillConversations: false,
|
|
// fillConversationMessages: false,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
if (project.IsNullOrDefault())
|
|
{
|
|
XException.NotFound.Throw();
|
|
}
|
|
|
|
//
|
|
// Check Conversation Provided or not ...
|
|
var hasConversation = !item.IsNullOrDefault();
|
|
|
|
//
|
|
// Normalize Conversation if Provided ...
|
|
if (hasConversation)
|
|
{
|
|
//
|
|
item.ProjectId = project.Id;
|
|
item.CreatedOn = DateTime.UtcNow;
|
|
|
|
//
|
|
// Validate Item ...
|
|
if (!item.IsValidForAddOrUpdate())
|
|
{
|
|
XException.InvalidData.Throw();
|
|
}
|
|
}
|
|
|
|
//
|
|
XAiConversationDto result = null;
|
|
|
|
//
|
|
// Create Provided Conversation ...
|
|
if (hasConversation)
|
|
{
|
|
//
|
|
result = await conversationRepositoryService.AddAsync(
|
|
item: item,
|
|
saveChanges: true,
|
|
// fillMessages: false,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
|
|
//
|
|
// Handling Send Push Notification ...
|
|
if (!result.IsNullOrDefault() &&
|
|
!connectionId.IsNullOrEmpty()
|
|
)
|
|
{
|
|
//
|
|
await SendPush(
|
|
connectionId: connectionId,
|
|
cancellationToken: cancellationToken,
|
|
payLoad: item.ToJSON(camelCase: true),
|
|
action: XAiDataProviderHubActions.ConversationCreated.GetStringValue()
|
|
);
|
|
}
|
|
}
|
|
//
|
|
// Check Default Conversation ...
|
|
else
|
|
{
|
|
//
|
|
// Check Default Conversation Exists or not ...
|
|
var hasDefault = await HasDefaultConversation(
|
|
projectId: project.Id,
|
|
ownerId: project.OwnerId,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
|
|
//
|
|
// If Default Project Exists, Throw Exception ...
|
|
if (hasDefault)
|
|
{
|
|
XException.InvalidArgs.Throw();
|
|
}
|
|
|
|
//
|
|
// Create and Retrive Default Conversation ...
|
|
result = await GetDefaultConversation(
|
|
projectId: project.Id,
|
|
ownerId: project.OwnerId,
|
|
connectionId: connectionId,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
}
|
|
|
|
//
|
|
// Validate ...
|
|
if (result.IsNullOrDefault())
|
|
{
|
|
XException.ActionFailed.Throw();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
public async Task<XAiMessageDto> AddMessage(
|
|
Guid conversationId,
|
|
XAiMessageDto item,
|
|
string connectionId = null,
|
|
CancellationToken cancellationToken = default
|
|
)
|
|
{
|
|
//
|
|
// Validate Args ...
|
|
if (item.IsNullOrDefault() ||
|
|
conversationId.IsNull() ||
|
|
conversationId.IsDefaultGuid()
|
|
)
|
|
{
|
|
XException.InvalidArgs.Throw();
|
|
}
|
|
|
|
//
|
|
// Normalize ...
|
|
item.CreatedOn = DateTime.UtcNow;
|
|
item.ConversationId = conversationId;
|
|
|
|
//
|
|
// Validate Item ...
|
|
if (!item.IsValidForAddOrUpdate())
|
|
{
|
|
XException.InvalidData.Throw();
|
|
}
|
|
|
|
//
|
|
var result = await messageRepositoryService.AddAsync(
|
|
item: item,
|
|
saveChanges: true,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
|
|
//
|
|
// Handling Send Push Notification ...
|
|
if (!result.IsNullOrDefault() &&
|
|
!connectionId.IsNullOrEmpty()
|
|
)
|
|
{
|
|
//
|
|
await SendPush(
|
|
connectionId: connectionId,
|
|
cancellationToken: cancellationToken,
|
|
payLoad: item.ToJSON(camelCase: true),
|
|
action: XAiDataProviderHubActions.MessageCreated.GetStringValue()
|
|
);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
#endregion
|
|
|
|
//
|
|
#region Updaters ...
|
|
#endregion
|
|
|
|
//
|
|
#region Defaults ...
|
|
/// <summary>
|
|
/// Retrieve Default Project of Specified Owner ...
|
|
/// Create it if not Handled ...
|
|
/// </summary>
|
|
/// <param name="ownerId"></param>
|
|
/// <param name="connectionId"></param>
|
|
/// <param name="cancellationToken"></param>
|
|
/// <returns></returns>
|
|
public async Task<XAiProjectDto> GetDefaultProject(
|
|
string ownerId,
|
|
string connectionId = null,
|
|
CancellationToken cancellationToken = default
|
|
)
|
|
{
|
|
//
|
|
// Check Default Project Exists or noit ...
|
|
var isExists = await HasDefaultProject(
|
|
ownerId: ownerId,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
if (!isExists)
|
|
{
|
|
//
|
|
await CreateDefaultProject(
|
|
ownerId: ownerId,
|
|
connectionId: connectionId,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
}
|
|
|
|
//
|
|
var resource = await stringProvider.FindOne(
|
|
cancellationToken: cancellationToken,
|
|
predicate: x =>
|
|
x.ResourceTitle
|
|
.ToNormalString()
|
|
.Contains(ownerId.ToNormalString()) &&
|
|
x.ResourceTitle
|
|
.ToNormalString()
|
|
.Contains(XAiModelsConstants.XAiProjectTitleIdentifier
|
|
.ToNormalString()) &&
|
|
x.TranslatedValue
|
|
.ToNormalString()
|
|
.Contains(XAiDataProviderConstants.XDefaultAiProjectSuffix)
|
|
);
|
|
if (resource.IsNullOrDefault())
|
|
{
|
|
XException.NotFound.Throw();
|
|
}
|
|
|
|
//
|
|
var result = await projectRepositoryService.FindOneAsync(
|
|
cancellationToken: cancellationToken,
|
|
predicate: x => x.Title
|
|
.Equals(
|
|
resource.ResourceTitle,
|
|
StringComparison.InvariantCultureIgnoreCase
|
|
)
|
|
);
|
|
if (result.IsNullOrDefault())
|
|
{
|
|
XException.NotFound.Throw();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieve Default Conversation of Specified Owner ...
|
|
/// Create it if not Handled ...
|
|
/// </summary>
|
|
/// <param name="ownerId"></param>
|
|
/// <param name="projectId"></param>
|
|
/// <param name="connectionId"></param>
|
|
/// <param name="cancellationToken"></param>
|
|
/// <returns></returns>
|
|
public async Task<XAiConversationDto> GetDefaultConversation(
|
|
string ownerId,
|
|
Guid projectId,
|
|
string connectionId = null,
|
|
CancellationToken cancellationToken = default
|
|
)
|
|
{
|
|
//
|
|
// Validate Args ...
|
|
if (ownerId.IsNullOrEmpty())
|
|
{
|
|
XException.InvalidArgs.Throw();
|
|
}
|
|
|
|
//
|
|
// Prepare Project ...
|
|
XAiProjectDto project = null;
|
|
if (projectId.IsNull() ||
|
|
projectId.IsDefaultGuid()
|
|
)
|
|
{
|
|
//
|
|
project = await GetDefaultProject(
|
|
ownerId: ownerId,
|
|
connectionId: connectionId,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
project = await projectRepositoryService.GetAsync(
|
|
id: project.Id,
|
|
includeBuilder: null,
|
|
ignoreSoftDeleteds: true,
|
|
// fillConversations: false,
|
|
// fillConversationMessages: false,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
}
|
|
if (project.IsNullOrDefault())
|
|
{
|
|
XException.NotFound.Throw();
|
|
}
|
|
|
|
//
|
|
// Check Default Conversation Exists or noit ...
|
|
var isExists = await HasDefaultConversation(
|
|
ownerId: ownerId,
|
|
projectId: project.Id,
|
|
connectionId: connectionId,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
if (!isExists)
|
|
{
|
|
//
|
|
await CreateDefaultConversation(
|
|
ownerId: ownerId,
|
|
projectId: project.Id,
|
|
connectionId: connectionId,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
}
|
|
|
|
//
|
|
// Detect Conversation Resource ...
|
|
var resource = await stringProvider.FindOne(
|
|
cancellationToken: cancellationToken,
|
|
predicate: x =>
|
|
x.ResourceTitle
|
|
.ToNormalString()
|
|
.Contains(ownerId.ToNormalString()) &&
|
|
x.ResourceTitle
|
|
.ToNormalString()
|
|
.Contains(XAiModelsConstants.XAiProjectTitleIdentifier
|
|
.ToNormalString()) &&
|
|
x.TranslatedValue
|
|
.ToNormalString()
|
|
.Contains(XAiDataProviderConstants.XDefaultAiProjectSuffix)
|
|
);
|
|
if (resource.IsNullOrDefault())
|
|
{
|
|
XException.NotFound.Throw();
|
|
}
|
|
|
|
//
|
|
// Find Default Conversation ...
|
|
var result = await conversationRepositoryService.FindOneAsync(
|
|
cancellationToken: cancellationToken,
|
|
predicate: x => x.Title
|
|
.Equals(
|
|
resource.ResourceTitle,
|
|
StringComparison.InvariantCultureIgnoreCase
|
|
) &&
|
|
x.ProjectId == project.Id
|
|
);
|
|
if (result.IsNullOrDefault())
|
|
{
|
|
XException.NotFound.Throw();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
#endregion
|
|
|
|
//
|
|
#region Enrichers ...
|
|
/// <summary>
|
|
/// Enrich Specified Item ...
|
|
/// </summary>
|
|
/// <param name="source"></param>
|
|
/// <param name="fillConversations"></param>
|
|
/// <param name="fillConversationMessages"></param>
|
|
/// <param name="cancellationToken"></param>
|
|
/// <returns></returns>
|
|
public async Task<XAiProjectDto> Enrich(
|
|
XAiProjectDto source,
|
|
bool fillConversations = false,
|
|
bool fillConversationMessages = false,
|
|
CancellationToken cancellationToken = default
|
|
)
|
|
{
|
|
//
|
|
var result = await projectEnricher.Enrich(
|
|
source: source,
|
|
fillConversations: fillConversations,
|
|
cancellationToken: cancellationToken,
|
|
fillConversationMessages: fillConversationMessages
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enrich Specified Items ...
|
|
/// </summary>
|
|
/// <param name="sources"></param>
|
|
/// <param name="fillConversations"></param>
|
|
/// <param name="fillConversationMessages"></param>
|
|
/// <param name="cancellationToken"></param>
|
|
/// <returns></returns>
|
|
public async Task<IEnumerable<XAiProjectDto>> EnrichRange(
|
|
IEnumerable<XAiProjectDto> sources,
|
|
bool fillConversations = false,
|
|
bool fillConversationMessages = false,
|
|
CancellationToken cancellationToken = default
|
|
)
|
|
{
|
|
//
|
|
var result = await projectEnricher.EnrichRange(
|
|
sources: sources,
|
|
fillConversations: fillConversations,
|
|
cancellationToken: cancellationToken,
|
|
fillConversationMessages: fillConversationMessages
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enrich Specified Item ...
|
|
/// </summary>
|
|
/// <param name="source"></param>
|
|
/// <param name="fillMessages"></param>
|
|
/// <param name="cancellationToken"></param>
|
|
/// <returns></returns>
|
|
public async Task<XAiConversationDto> Enrich(
|
|
XAiConversationDto source,
|
|
bool fillMessages = false,
|
|
CancellationToken cancellationToken = default
|
|
)
|
|
{
|
|
//
|
|
var result = await conversationEnricher.Enrich(
|
|
source: source,
|
|
fillMessages: fillMessages,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enrich Specified Items ...
|
|
/// </summary>
|
|
/// <param name="sources"></param>
|
|
/// <param name="fillMessages"></param>
|
|
/// <param name="cancellationToken"></param>
|
|
/// <returns></returns>
|
|
public async Task<IEnumerable<XAiConversationDto>> EnrichRange(
|
|
IEnumerable<XAiConversationDto> sources,
|
|
bool fillMessages = false,
|
|
CancellationToken cancellationToken = default
|
|
)
|
|
{
|
|
//
|
|
var result = await conversationEnricher.EnrichRange(
|
|
sources: sources,
|
|
fillMessages: fillMessages,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enrich Specified Item ...
|
|
/// </summary>
|
|
/// <param name="source"></param>
|
|
/// <param name="cancellationToken"></param>
|
|
/// <returns></returns>
|
|
public async Task<XAiMessageDto> Enrich(
|
|
XAiMessageDto source,
|
|
CancellationToken cancellationToken = default
|
|
)
|
|
{
|
|
//
|
|
var result = await messageEnricher.Enrich(
|
|
source: source,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enrich Specified Items ...
|
|
/// </summary>
|
|
/// <param name="sources"></param>
|
|
/// <param name="cancellationToken"></param>
|
|
/// <returns></returns>
|
|
public async Task<IEnumerable<XAiMessageDto>> EnrichRange(
|
|
IEnumerable<XAiMessageDto> sources,
|
|
CancellationToken cancellationToken = default
|
|
)
|
|
{
|
|
//
|
|
var result = await messageEnricher.EnrichRange(
|
|
sources: sources,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
#endregion
|
|
|
|
//
|
|
#region Private ...
|
|
/// <summary>
|
|
/// Check Default Project Exists or not ...
|
|
/// </summary>
|
|
/// <param name="ownerId"></param>
|
|
/// <param name="cancellationToken"></param>
|
|
/// <returns></returns>
|
|
private async Task<bool> HasDefaultProject(
|
|
string ownerId,
|
|
CancellationToken cancellationToken = default
|
|
)
|
|
{
|
|
//
|
|
// Validate Args ...
|
|
var result = !ownerId.IsNullOrEmpty();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Default Owner Exists or not ...
|
|
result = !(await stringProvider.FindOne(
|
|
cancellationToken: cancellationToken,
|
|
predicate: x =>
|
|
x.ResourceTitle
|
|
.ToNormalString()
|
|
.Contains(ownerId.ToNormalString()) &&
|
|
x.ResourceTitle
|
|
.ToNormalString()
|
|
.Contains(XAiModelsConstants.XAiProjectTitleIdentifier
|
|
.ToNormalString()) &&
|
|
x.TranslatedValue
|
|
.ToNormalString()
|
|
.Contains(XAiDataProviderConstants.XDefaultAiProjectSuffix)
|
|
))
|
|
.IsNullOrDefault();
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create Default Project for Specified Owner ...
|
|
/// </summary>
|
|
/// <param name="ownerId"></param>
|
|
/// <param name="connectionId"></param>
|
|
/// <param name="cancellationToken"></param>
|
|
/// <returns></returns>
|
|
private async Task CreateDefaultProject(
|
|
string ownerId,
|
|
string connectionId = null,
|
|
CancellationToken cancellationToken = default
|
|
)
|
|
{
|
|
//
|
|
if (ownerId.IsNullOrEmpty())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
var defaultLang = appConfiguration.DefaultLanguage;
|
|
|
|
//
|
|
// Check Default Owner Exists or not ...
|
|
var isExists = await HasDefaultProject(
|
|
ownerId: ownerId,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
if (isExists)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Create Default ...
|
|
var item = new XAiProjectDto()
|
|
{
|
|
OwnerId = ownerId,
|
|
CreatedOn = DateTime.UtcNow,
|
|
Title = Guid.NewGuid().ToString(),
|
|
Description = Guid.NewGuid().ToString(),
|
|
};
|
|
item = await projectRepositoryService.AddAsync(
|
|
item: item,
|
|
saveChanges: true,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
|
|
//
|
|
// Prepare Tile and Description Resource Ids ...
|
|
var titleResource = await projectTitleResourceProvider.AddOrUpdateLocale(
|
|
owner: ownerId,
|
|
identifier: item.Id,
|
|
locale: new XLocaleResourceDto
|
|
{
|
|
Language = defaultLang,
|
|
Value = XAiDataProviderConstants.XDefaultAiProjectSuffix
|
|
},
|
|
cancellationToken: cancellationToken
|
|
);
|
|
var descriptionResource = await projectDescriptionResourceProvider.AddOrUpdateLocale(
|
|
owner: ownerId,
|
|
identifier: item.Id,
|
|
new XLocaleResourceDto
|
|
{
|
|
Language = defaultLang,
|
|
Value = XAiDataProviderConstants.XDefaultAiProjectSuffix
|
|
},
|
|
cancellationToken: cancellationToken
|
|
);
|
|
if (titleResource.IsNullOrDefault() ||
|
|
descriptionResource.IsNullOrDefault()
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Update Project Resources ...
|
|
item.Title = titleResource.Resource;
|
|
item.Description = descriptionResource.Resource;
|
|
item = await projectRepositoryService.UpdateAsync(
|
|
id: item.Id,
|
|
item: item,
|
|
saveChanges: true,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
|
|
//
|
|
// Sending Push ...
|
|
if (!connectionId.IsNullOrEmpty())
|
|
{
|
|
//
|
|
await SendPush(
|
|
connectionId: connectionId,
|
|
cancellationToken: cancellationToken,
|
|
payLoad: item.ToJSON(camelCase: true),
|
|
action: XAiDataProviderHubActions.ProjectCreated.GetStringValue()
|
|
);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check Default Conversation Exists or not ...
|
|
/// </summary>
|
|
/// <param name="ownerId"></param>
|
|
/// <param name="projectId"></param>
|
|
/// <param name="connectionId"></param>
|
|
/// <param name="cancellationToken"></param>
|
|
/// <returns></returns>
|
|
private async Task<bool> HasDefaultConversation(
|
|
string ownerId,
|
|
Guid projectId,
|
|
string connectionId = null,
|
|
CancellationToken cancellationToken = default
|
|
)
|
|
{
|
|
//
|
|
// Validate Args ...
|
|
var result = !ownerId.IsNullOrEmpty();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Prepare Project ...
|
|
XAiProjectDto project = null;
|
|
if (projectId.IsNull() ||
|
|
projectId.IsDefaultGuid()
|
|
)
|
|
{
|
|
//
|
|
project = await GetDefaultProject(
|
|
ownerId: ownerId,
|
|
connectionId: connectionId,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
project = await projectRepositoryService.GetAsync(
|
|
id: project.Id,
|
|
includeBuilder: null,
|
|
ignoreSoftDeleteds: true,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
}
|
|
if (project.IsNullOrDefault())
|
|
{
|
|
XException.NotFound.Throw();
|
|
}
|
|
|
|
//
|
|
// Check Default Owner Exists or not ...
|
|
var resource = await stringProvider.FindOne(
|
|
cancellationToken: cancellationToken,
|
|
predicate: x =>
|
|
x.ResourceTitle
|
|
.ToNormalString()
|
|
.Contains(projectId.ToString().ToNormalString()) &&
|
|
x.ResourceTitle
|
|
.ToNormalString()
|
|
.Contains(XAiModelsConstants.XAiConversationTitleIdentifier
|
|
.ToNormalString()) &&
|
|
x.TranslatedValue
|
|
.ToNormalString()
|
|
.Contains(XAiDataProviderConstants.XDefaultAiConversationSuffix)
|
|
);
|
|
result = !resource.IsNullOrDefault();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = !(await conversationRepositoryService.FindOneAsync(
|
|
cancellationToken: cancellationToken,
|
|
predicate: x =>
|
|
x.ProjectId == projectId &&
|
|
x.Title == resource.ResourceTitle
|
|
))
|
|
.IsNullOrDefault();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check Default Conversation Exists or not ...
|
|
/// </summary>
|
|
/// <param name="ownerId"></param>
|
|
/// <param name="projectId"></param>
|
|
/// <param name="connectionId"></param>
|
|
/// <param name="cancellationToken"></param>
|
|
/// <returns></returns>
|
|
private async Task CreateDefaultConversation(
|
|
string ownerId,
|
|
Guid projectId,
|
|
string connectionId = null,
|
|
CancellationToken cancellationToken = default
|
|
)
|
|
{
|
|
//
|
|
// Validate Args ...
|
|
var isValid = !ownerId.IsNullOrEmpty();
|
|
if (!isValid)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
var defaultLang = appConfiguration.DefaultLanguage;
|
|
|
|
//
|
|
// Prepare Project ...
|
|
XAiProjectDto project = null;
|
|
if (projectId.IsNull() ||
|
|
projectId.IsDefaultGuid()
|
|
)
|
|
{
|
|
//
|
|
project = await GetDefaultProject(
|
|
ownerId: ownerId,
|
|
connectionId: connectionId,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
project = await projectRepositoryService.GetAsync(
|
|
id: project.Id,
|
|
includeBuilder: null,
|
|
ignoreSoftDeleteds: true,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
}
|
|
if (project.IsNullOrDefault())
|
|
{
|
|
XException.NotFound.Throw();
|
|
}
|
|
|
|
//
|
|
// Check Default Owner Exists or not ...
|
|
isValid = await HasDefaultConversation(
|
|
ownerId: ownerId,
|
|
projectId: project.Id,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
if (isValid)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Create Default Conversation ...
|
|
var item = new XAiConversationDto
|
|
{
|
|
OwnerId = ownerId,
|
|
ProjectId = project.Id,
|
|
CreatedOn = DateTime.UtcNow,
|
|
Title = Guid.NewGuid().ToString()
|
|
};
|
|
item = await conversationRepositoryService.AddAsync(
|
|
item: item,
|
|
saveChanges: true,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
|
|
//
|
|
// Prepare Title Resource Ids ...
|
|
var titleResource = await conversationTitleResourceProvider.AddOrUpdateLocale(
|
|
owner: ownerId,
|
|
identifier: item.Id,
|
|
locale: new XLocaleResourceDto
|
|
{
|
|
Language = defaultLang,
|
|
Value = XAiDataProviderConstants.XDefaultAiConversationSuffix
|
|
},
|
|
cancellationToken: cancellationToken
|
|
);
|
|
if (titleResource.IsNullOrDefault())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Update Conversation Resources ...
|
|
item.Title = titleResource.Resource;
|
|
item = await conversationRepositoryService.UpdateAsync(
|
|
item: item,
|
|
id: item.Id,
|
|
saveChanges: true,
|
|
cancellationToken: cancellationToken
|
|
);
|
|
|
|
//
|
|
// Sending Push ...
|
|
if (!connectionId.IsNullOrEmpty())
|
|
{
|
|
//
|
|
await SendPush(
|
|
connectionId: connectionId,
|
|
cancellationToken: cancellationToken,
|
|
payLoad: item.ToJSON(camelCase: true),
|
|
action: XAiDataProviderHubActions.ConversationCreated.GetStringValue()
|
|
);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Send Custom Push Message ...
|
|
/// </summary>
|
|
/// <param name="action"></param>
|
|
/// <param name="payLoad"></param>
|
|
/// <param name="connectionId"></param>
|
|
/// <param name="cancellationToken"></param>
|
|
/// <returns></returns>
|
|
public async Task SendPush(
|
|
string action,
|
|
string payLoad,
|
|
string connectionId = null,
|
|
CancellationToken cancellationToken = default
|
|
)
|
|
{
|
|
//
|
|
try
|
|
{
|
|
//
|
|
// Collect Allowed Actions ...
|
|
var actions = new List<string>
|
|
{
|
|
XAiDataProviderHubActions.ProjectCreated.GetStringValue(),
|
|
XAiDataProviderHubActions.ProjectUpdated.GetStringValue(),
|
|
XAiDataProviderHubActions.ProjectRemoved.GetStringValue(),
|
|
XAiDataProviderHubActions.MessageCreated.GetStringValue(),
|
|
XAiDataProviderHubActions.MessageUpdated.GetStringValue(),
|
|
XAiDataProviderHubActions.MessageRemoved.GetStringValue(),
|
|
XAiDataProviderHubActions.ConversationCreated.GetStringValue(),
|
|
XAiDataProviderHubActions.ConversationUpdated.GetStringValue(),
|
|
XAiDataProviderHubActions.ConversationRemoved.GetStringValue(),
|
|
};
|
|
|
|
//
|
|
// Validate Args ...
|
|
var isValid =
|
|
!action.IsNullOrEmpty() &&
|
|
actions.Contains(action);
|
|
if (!isValid)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Retrieve Connection Id ...
|
|
var clients = hub.Clients.All;
|
|
if (!connectionId.IsNullOrEmpty())
|
|
{
|
|
clients = hub.Clients.AllExcept(connectionId);
|
|
}
|
|
|
|
//
|
|
await clients.SendAsync(
|
|
action,
|
|
payLoad,
|
|
connectionId,
|
|
cancellationToken
|
|
);
|
|
}
|
|
catch { }
|
|
}
|
|
#endregion
|
|
}
|
|
} |