Удалены чувствительные данные
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
using Vortex.Modules.Chats.Domain;
|
||||
using Vortex.Shared.Kernel;
|
||||
using Vortex.Modules.Chats.Application.Abstractions;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Vortex.Modules.Chats.Infrastructure.SignalR;
|
||||
using MediatR;
|
||||
|
||||
namespace Vortex.Modules.Chats.Application.Messages.React;
|
||||
|
||||
public sealed record AddReactionCommand(
|
||||
Guid MessageId,
|
||||
Guid UserId,
|
||||
string Emoji,
|
||||
Guid ChatId) : ICommand;
|
||||
|
||||
public sealed class AddReactionCommandHandler : ICommandHandler<AddReactionCommand>
|
||||
{
|
||||
private readonly IMessageRepository _messageRepository;
|
||||
private readonly IChatsUnitOfWork _unitOfWork;
|
||||
private readonly IHubContext<ChatHub> _hubContext;
|
||||
private readonly IUserDisplayNameProvider _displayNameProvider;
|
||||
|
||||
public AddReactionCommandHandler(
|
||||
IMessageRepository messageRepository,
|
||||
IChatsUnitOfWork unitOfWork,
|
||||
IHubContext<ChatHub> hubContext,
|
||||
IUserDisplayNameProvider displayNameProvider)
|
||||
{
|
||||
_messageRepository = messageRepository;
|
||||
_unitOfWork = unitOfWork;
|
||||
_hubContext = hubContext;
|
||||
_displayNameProvider = displayNameProvider;
|
||||
}
|
||||
|
||||
public async Task<Result> Handle(AddReactionCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var message = await _messageRepository.GetByIdAsync(request.MessageId, cancellationToken);
|
||||
if (message is null) return Result.Failure(new Error("Messages.NotFound", "Message not found."));
|
||||
|
||||
message.AddReaction(request.UserId, request.Emoji);
|
||||
|
||||
await _unitOfWork.SaveChangesAsync(cancellationToken);
|
||||
|
||||
var username = await _displayNameProvider.GetDisplayNameAsync(request.UserId, cancellationToken);
|
||||
|
||||
await _hubContext.Clients.Group(request.ChatId.ToString()).SendAsync("reaction_added", new
|
||||
{
|
||||
messageId = request.MessageId,
|
||||
chatId = request.ChatId,
|
||||
userId = request.UserId,
|
||||
username = username,
|
||||
emoji = request.Emoji
|
||||
});
|
||||
|
||||
return Result.Success();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using Vortex.Modules.Chats.Domain;
|
||||
using Vortex.Shared.Kernel;
|
||||
using Vortex.Modules.Chats.Application.Abstractions;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Vortex.Modules.Chats.Infrastructure.SignalR;
|
||||
using MediatR;
|
||||
|
||||
namespace Vortex.Modules.Chats.Application.Messages.React;
|
||||
|
||||
public sealed record RemoveReactionCommand(
|
||||
Guid MessageId,
|
||||
Guid UserId,
|
||||
string Emoji,
|
||||
Guid ChatId) : ICommand;
|
||||
|
||||
public sealed class RemoveReactionCommandHandler : ICommandHandler<RemoveReactionCommand>
|
||||
{
|
||||
private readonly IMessageRepository _messageRepository;
|
||||
private readonly IChatsUnitOfWork _unitOfWork;
|
||||
private readonly IHubContext<ChatHub> _hubContext;
|
||||
|
||||
public RemoveReactionCommandHandler(
|
||||
IMessageRepository messageRepository,
|
||||
IChatsUnitOfWork unitOfWork,
|
||||
IHubContext<ChatHub> hubContext)
|
||||
{
|
||||
_messageRepository = messageRepository;
|
||||
_unitOfWork = unitOfWork;
|
||||
_hubContext = hubContext;
|
||||
}
|
||||
|
||||
public async Task<Result> Handle(RemoveReactionCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var message = await _messageRepository.GetByIdAsync(request.MessageId, cancellationToken);
|
||||
if (message is null) return Result.Failure(new Error("Messages.NotFound", "Message not found."));
|
||||
|
||||
message.RemoveReaction(request.UserId, request.Emoji);
|
||||
|
||||
await _unitOfWork.SaveChangesAsync(cancellationToken);
|
||||
|
||||
await _hubContext.Clients.Group(request.ChatId.ToString()).SendAsync("reaction_removed", new
|
||||
{
|
||||
messageId = request.MessageId,
|
||||
chatId = request.ChatId,
|
||||
userId = request.UserId,
|
||||
emoji = request.Emoji
|
||||
});
|
||||
|
||||
return Result.Success();
|
||||
}
|
||||
}
|
||||
@@ -7,15 +7,17 @@ namespace Vortex.Modules.Chats.Application.Messages.Send;
|
||||
/// <summary>
|
||||
/// Команда для отправки сообщения в чат.
|
||||
/// </summary>
|
||||
public record AttachmentRequest(string Type, string Url, string? FileName, long? FileSize);
|
||||
|
||||
public sealed record SendMessageCommand(
|
||||
Guid ChatId,
|
||||
Guid SenderId,
|
||||
string? Content,
|
||||
string Type,
|
||||
string? MediaUrl = null,
|
||||
string? MediaType = null,
|
||||
string? FileName = null,
|
||||
long? FileSize = null) : ICommand<Guid>;
|
||||
List<AttachmentRequest>? Attachments = null,
|
||||
Guid? ReplyToId = null,
|
||||
string? Quote = null,
|
||||
Guid? ForwardedFromId = null) : ICommand<Guid>;
|
||||
|
||||
public sealed class SendMessageCommandHandler : ICommandHandler<SendMessageCommand, Guid>
|
||||
{
|
||||
@@ -50,11 +52,17 @@ public sealed class SendMessageCommandHandler : ICommandHandler<SendMessageComma
|
||||
request.ChatId,
|
||||
request.SenderId,
|
||||
request.Content,
|
||||
request.Type);
|
||||
request.Type,
|
||||
request.ReplyToId,
|
||||
request.Quote,
|
||||
request.ForwardedFromId);
|
||||
|
||||
if (!string.IsNullOrEmpty(request.MediaUrl) && !string.IsNullOrEmpty(request.MediaType))
|
||||
if (request.Attachments != null && request.Attachments.Any())
|
||||
{
|
||||
message.AddMedia(request.MediaType, request.MediaUrl, request.FileName, request.FileSize);
|
||||
foreach (var att in request.Attachments)
|
||||
{
|
||||
message.AddMedia(att.Type, att.Url, att.FileName, att.FileSize);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Сохраняем
|
||||
|
||||
@@ -20,6 +20,7 @@ public sealed class Message : AggregateRoot<Guid>
|
||||
public string? Quote { get; private set; }
|
||||
public bool IsEdited { get; private set; }
|
||||
public bool IsDeleted { get; private set; }
|
||||
public Guid? ForwardedFromId { get; private set; }
|
||||
public DateTime CreatedAt { get; private set; }
|
||||
|
||||
private readonly List<Media> _media = new();
|
||||
@@ -28,20 +29,23 @@ public sealed class Message : AggregateRoot<Guid>
|
||||
private readonly List<ReadReceipt> _readBy = new();
|
||||
public IReadOnlyCollection<ReadReceipt> ReadBy => _readBy.AsReadOnly();
|
||||
|
||||
private Message(Guid id, Guid chatId, Guid senderId, string? content, string type) : base(id)
|
||||
private Message(Guid id, Guid chatId, Guid senderId, string? content, string type, Guid? replyToId = null, string? quote = null, Guid? forwardedFromId = null) : base(id)
|
||||
{
|
||||
ChatId = chatId;
|
||||
SenderId = senderId;
|
||||
Content = content;
|
||||
Type = type;
|
||||
ReplyToId = replyToId;
|
||||
Quote = quote;
|
||||
ForwardedFromId = forwardedFromId;
|
||||
CreatedAt = DateTime.UtcNow;
|
||||
|
||||
RaiseDomainEvent(new MessageSentDomainEvent(Id, ChatId, SenderId, Content));
|
||||
}
|
||||
|
||||
public static Message Create(Guid chatId, Guid senderId, string? content, string type)
|
||||
public static Message Create(Guid chatId, Guid senderId, string? content, string type, Guid? replyToId = null, string? quote = null, Guid? forwardedFromId = null)
|
||||
{
|
||||
return new Message(Guid.NewGuid(), chatId, senderId, content, type);
|
||||
return new Message(Guid.NewGuid(), chatId, senderId, content, type, replyToId, quote, forwardedFromId);
|
||||
}
|
||||
|
||||
public void AddMedia(string type, string url, string? filename, long? size)
|
||||
@@ -49,6 +53,27 @@ public sealed class Message : AggregateRoot<Guid>
|
||||
_media.Add(new Media(Id, type, url, filename, size));
|
||||
}
|
||||
|
||||
private readonly List<Reaction> _reactions = new();
|
||||
public IReadOnlyCollection<Reaction> Reactions => _reactions.AsReadOnly();
|
||||
|
||||
public void AddReaction(Guid userId, string emoji)
|
||||
{
|
||||
var existing = _reactions.Find(r => r.UserId == userId && r.Emoji == emoji);
|
||||
if (existing == null)
|
||||
{
|
||||
_reactions.Add(new Reaction(Id, userId, emoji));
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveReaction(Guid userId, string emoji)
|
||||
{
|
||||
var existing = _reactions.Find(r => r.UserId == userId && r.Emoji == emoji);
|
||||
if (existing != null)
|
||||
{
|
||||
_reactions.Remove(existing);
|
||||
}
|
||||
}
|
||||
|
||||
public void Edit(string newContent)
|
||||
{
|
||||
Content = newContent;
|
||||
@@ -61,6 +86,22 @@ public sealed class Message : AggregateRoot<Guid>
|
||||
IsDeleted = true;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Реакция на сообщение.
|
||||
/// </summary>
|
||||
public sealed class Reaction : Entity<Guid>
|
||||
{
|
||||
public Guid MessageId { get; private set; }
|
||||
public Guid UserId { get; private set; }
|
||||
public string Emoji { get; private set; }
|
||||
|
||||
internal Reaction(Guid messageId, Guid userId, string emoji) : base(Guid.NewGuid())
|
||||
{
|
||||
MessageId = messageId;
|
||||
UserId = userId;
|
||||
Emoji = emoji;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Медиа-файл, прикрепленный к сообщению.
|
||||
|
||||
@@ -36,6 +36,37 @@ public sealed class MessageSentDomainEventHandler : INotificationHandler<Message
|
||||
? new { Id = userInfo.Id, Username = userInfo.Username, DisplayName = userInfo.DisplayName, Avatar = userInfo.Avatar }
|
||||
: new { Id = message.SenderId, Username = "unknown", DisplayName = "Unknown", Avatar = (string?)null };
|
||||
|
||||
// Fetch forwarded from info if exists
|
||||
object? forwardedFromObj = null;
|
||||
if (message.ForwardedFromId.HasValue)
|
||||
{
|
||||
var fwdUserInfo = await _displayNameProvider.GetUserInfoAsync(message.ForwardedFromId.Value, cancellationToken);
|
||||
forwardedFromObj = fwdUserInfo != null
|
||||
? new { Id = fwdUserInfo.Id, Username = fwdUserInfo.Username, DisplayName = fwdUserInfo.DisplayName, Avatar = fwdUserInfo.Avatar }
|
||||
: new { Id = message.ForwardedFromId.Value, Username = "unknown", DisplayName = "Unknown", Avatar = (string?)null };
|
||||
}
|
||||
|
||||
// Fetch reply info if exists
|
||||
object? replyToObj = null;
|
||||
if (message.ReplyToId.HasValue)
|
||||
{
|
||||
var replyMsg = await _messageRepository.GetByIdAsync(message.ReplyToId.Value, cancellationToken);
|
||||
if (replyMsg != null)
|
||||
{
|
||||
var replySenderInfo = await _displayNameProvider.GetUserInfoAsync(replyMsg.SenderId, cancellationToken);
|
||||
replyToObj = new
|
||||
{
|
||||
Id = replyMsg.Id,
|
||||
Content = replyMsg.Content,
|
||||
Quote = message.Quote,
|
||||
media = replyMsg.Media.Select(rm => new { rm.Id, rm.Type, rm.Url }).ToList(),
|
||||
Sender = replySenderInfo != null
|
||||
? new { Id = replySenderInfo.Id, Username = replySenderInfo.Username, DisplayName = replySenderInfo.DisplayName }
|
||||
: new { Id = replyMsg.SenderId, Username = "unknown", DisplayName = "Unknown" }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Отправляем сообщение в "комнату" чата.
|
||||
await _hubContext.Clients.Group(notification.ChatId.ToString())
|
||||
.SendAsync("new_message", new
|
||||
@@ -46,7 +77,18 @@ public sealed class MessageSentDomainEventHandler : INotificationHandler<Message
|
||||
message.Content,
|
||||
message.Type,
|
||||
message.CreatedAt,
|
||||
Media = message.Media.ToList(),
|
||||
message.ForwardedFromId,
|
||||
ForwardedFrom = forwardedFromObj,
|
||||
message.ReplyToId,
|
||||
ReplyTo = replyToObj,
|
||||
message.Quote,
|
||||
Media = message.Media.Select(m => new {
|
||||
m.Id,
|
||||
m.Type,
|
||||
m.Url,
|
||||
Filename = m.Filename,
|
||||
Size = m.Size
|
||||
}).ToList(),
|
||||
Sender = senderObj,
|
||||
Reactions = new List<object>(),
|
||||
ReadBy = new List<object>()
|
||||
|
||||
@@ -54,6 +54,14 @@ public sealed class ChatsDbContext : DbContext, IChatsUnitOfWork
|
||||
mb.HasKey(x => x.Id);
|
||||
mb.WithOwner().HasForeignKey(x => x.MessageId);
|
||||
});
|
||||
|
||||
builder.OwnsMany(m => m.Reactions, mb =>
|
||||
{
|
||||
mb.ToTable("MessageReactions");
|
||||
mb.HasKey(x => x.Id);
|
||||
mb.WithOwner().HasForeignKey(x => x.MessageId);
|
||||
mb.HasIndex(x => new { x.MessageId, x.UserId, x.Emoji }).IsUnique();
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity<ReadReceipt>(builder =>
|
||||
|
||||
@@ -22,6 +22,7 @@ public sealed class MessageRepository : IMessageRepository
|
||||
return await _dbContext.Messages
|
||||
.Include(m => m.Media)
|
||||
.Include(m => m.ReadBy)
|
||||
.Include(m => m.Reactions)
|
||||
.FirstOrDefaultAsync(m => m.Id == id, cancellationToken);
|
||||
}
|
||||
|
||||
@@ -34,6 +35,7 @@ public sealed class MessageRepository : IMessageRepository
|
||||
.Take(limit)
|
||||
.Include(m => m.Media)
|
||||
.Include(m => m.ReadBy)
|
||||
.Include(m => m.Reactions)
|
||||
.ToListAsync(cancellationToken);
|
||||
}
|
||||
|
||||
@@ -50,6 +52,7 @@ public sealed class MessageRepository : IMessageRepository
|
||||
.Take(50)
|
||||
.Include(m => m.Media)
|
||||
.Include(m => m.ReadBy)
|
||||
.Include(m => m.Reactions)
|
||||
.ToListAsync(cancellationToken);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using Vortex.Modules.Chats.Infrastructure.Persistence;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Vortex.Modules.Chats.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
[DbContext(typeof(ChatsDbContext))]
|
||||
[Migration("20260312094130_AddForwardedFromToMessages")]
|
||||
partial class AddForwardedFromToMessages
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasDefaultSchema("chats")
|
||||
.HasAnnotation("ProductVersion", "10.0.4")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Vortex.Modules.Chats.Domain.Chat", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Avatar")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Chats", "chats");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Vortex.Modules.Chats.Domain.Message", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("ChatId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Content")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid?>("ForwardedFromId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<bool>("IsEdited")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("Quote")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid?>("ReplyToId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("SenderId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Messages", "chats");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Vortex.Modules.Chats.Domain.ReadReceipt", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("MessageId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("ReadAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("MessageId", "UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("ReadReceipts", "chats");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Vortex.Modules.Chats.Domain.Chat", b =>
|
||||
{
|
||||
b.OwnsMany("Vortex.Modules.Chats.Domain.ChatMember", "Members", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<Guid>("ChatId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<bool>("IsMuted")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b1.Property<DateTime>("JoinedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b1.Property<string>("Role")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b1.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.HasKey("Id");
|
||||
|
||||
b1.HasIndex("ChatId", "UserId")
|
||||
.IsUnique();
|
||||
|
||||
b1.ToTable("ChatMembers", "chats");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("ChatId");
|
||||
});
|
||||
|
||||
b.Navigation("Members");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Vortex.Modules.Chats.Domain.Message", b =>
|
||||
{
|
||||
b.OwnsMany("Vortex.Modules.Chats.Domain.Media", "Media", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<string>("Filename")
|
||||
.HasColumnType("text");
|
||||
|
||||
b1.Property<Guid>("MessageId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<long?>("Size")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b1.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b1.Property<string>("Url")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b1.HasKey("Id");
|
||||
|
||||
b1.HasIndex("MessageId");
|
||||
|
||||
b1.ToTable("MessageMedia", "chats");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("MessageId");
|
||||
});
|
||||
|
||||
b.Navigation("Media");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Vortex.Modules.Chats.Domain.ReadReceipt", b =>
|
||||
{
|
||||
b.HasOne("Vortex.Modules.Chats.Domain.Message", null)
|
||||
.WithMany("ReadBy")
|
||||
.HasForeignKey("MessageId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Vortex.Modules.Chats.Domain.Message", b =>
|
||||
{
|
||||
b.Navigation("ReadBy");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Vortex.Modules.Chats.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddForwardedFromToMessages : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "ForwardedFromId",
|
||||
schema: "chats",
|
||||
table: "Messages",
|
||||
type: "uuid",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ForwardedFromId",
|
||||
schema: "chats",
|
||||
table: "Messages");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using Vortex.Modules.Chats.Infrastructure.Persistence;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Vortex.Modules.Chats.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
[DbContext(typeof(ChatsDbContext))]
|
||||
[Migration("20260312100324_AddReactionsToMessages")]
|
||||
partial class AddReactionsToMessages
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasDefaultSchema("chats")
|
||||
.HasAnnotation("ProductVersion", "10.0.4")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Vortex.Modules.Chats.Domain.Chat", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Avatar")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Chats", "chats");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Vortex.Modules.Chats.Domain.Message", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("ChatId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Content")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid?>("ForwardedFromId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<bool>("IsEdited")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("Quote")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid?>("ReplyToId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("SenderId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Messages", "chats");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Vortex.Modules.Chats.Domain.ReadReceipt", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("MessageId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("ReadAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("MessageId", "UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("ReadReceipts", "chats");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Vortex.Modules.Chats.Domain.Chat", b =>
|
||||
{
|
||||
b.OwnsMany("Vortex.Modules.Chats.Domain.ChatMember", "Members", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<Guid>("ChatId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<bool>("IsMuted")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b1.Property<DateTime>("JoinedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b1.Property<string>("Role")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b1.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.HasKey("Id");
|
||||
|
||||
b1.HasIndex("ChatId", "UserId")
|
||||
.IsUnique();
|
||||
|
||||
b1.ToTable("ChatMembers", "chats");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("ChatId");
|
||||
});
|
||||
|
||||
b.Navigation("Members");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Vortex.Modules.Chats.Domain.Message", b =>
|
||||
{
|
||||
b.OwnsMany("Vortex.Modules.Chats.Domain.Media", "Media", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<string>("Filename")
|
||||
.HasColumnType("text");
|
||||
|
||||
b1.Property<Guid>("MessageId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<long?>("Size")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b1.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b1.Property<string>("Url")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b1.HasKey("Id");
|
||||
|
||||
b1.HasIndex("MessageId");
|
||||
|
||||
b1.ToTable("MessageMedia", "chats");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("MessageId");
|
||||
});
|
||||
|
||||
b.OwnsMany("Vortex.Modules.Chats.Domain.Reaction", "Reactions", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<string>("Emoji")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b1.Property<Guid>("MessageId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.HasKey("Id");
|
||||
|
||||
b1.HasIndex("MessageId", "UserId", "Emoji")
|
||||
.IsUnique();
|
||||
|
||||
b1.ToTable("MessageReactions", "chats");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("MessageId");
|
||||
});
|
||||
|
||||
b.Navigation("Media");
|
||||
|
||||
b.Navigation("Reactions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Vortex.Modules.Chats.Domain.ReadReceipt", b =>
|
||||
{
|
||||
b.HasOne("Vortex.Modules.Chats.Domain.Message", null)
|
||||
.WithMany("ReadBy")
|
||||
.HasForeignKey("MessageId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Vortex.Modules.Chats.Domain.Message", b =>
|
||||
{
|
||||
b.Navigation("ReadBy");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Vortex.Modules.Chats.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddReactionsToMessages : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "MessageReactions",
|
||||
schema: "chats",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
MessageId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
UserId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Emoji = table.Column<string>(type: "text", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_MessageReactions", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_MessageReactions_Messages_MessageId",
|
||||
column: x => x.MessageId,
|
||||
principalSchema: "chats",
|
||||
principalTable: "Messages",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_MessageReactions_MessageId_UserId_Emoji",
|
||||
schema: "chats",
|
||||
table: "MessageReactions",
|
||||
columns: new[] { "MessageId", "UserId", "Emoji" },
|
||||
unique: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "MessageReactions",
|
||||
schema: "chats");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,6 +62,9 @@ namespace Vortex.Modules.Chats.Infrastructure.Persistence.Migrations
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid?>("ForwardedFromId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
@@ -182,7 +185,36 @@ namespace Vortex.Modules.Chats.Infrastructure.Persistence.Migrations
|
||||
.HasForeignKey("MessageId");
|
||||
});
|
||||
|
||||
b.OwnsMany("Vortex.Modules.Chats.Domain.Reaction", "Reactions", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<string>("Emoji")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b1.Property<Guid>("MessageId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.HasKey("Id");
|
||||
|
||||
b1.HasIndex("MessageId", "UserId", "Emoji")
|
||||
.IsUnique();
|
||||
|
||||
b1.ToTable("MessageReactions", "chats");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("MessageId");
|
||||
});
|
||||
|
||||
b.Navigation("Media");
|
||||
|
||||
b.Navigation("Reactions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Vortex.Modules.Chats.Domain.ReadReceipt", b =>
|
||||
|
||||
@@ -76,15 +76,18 @@ public sealed class ChatHub : Hub
|
||||
[HubMethodName("send_message")]
|
||||
public async Task SendMessage(SendMessageHubRequest request)
|
||||
{
|
||||
var attachments = request.Attachments?.Select(a =>
|
||||
new AttachmentRequest(a.Type, a.Url, a.FileName, a.FileSize)).ToList();
|
||||
|
||||
var command = new SendMessageCommand(
|
||||
request.ChatId,
|
||||
_userContext.UserId,
|
||||
request.Content,
|
||||
request.Type,
|
||||
request.MediaUrl,
|
||||
request.MediaType,
|
||||
request.FileName,
|
||||
request.FileSize);
|
||||
attachments,
|
||||
request.ReplyToId,
|
||||
request.Quote,
|
||||
request.ForwardedFromId);
|
||||
|
||||
await _sender.Send(command);
|
||||
}
|
||||
@@ -127,6 +130,22 @@ public sealed class ChatHub : Hub
|
||||
await Clients.Group(chatId).SendAsync("user_stopped_typing", new { ChatId = chatId, UserId = _userContext.UserId });
|
||||
}
|
||||
|
||||
[HubMethodName("add_reaction")]
|
||||
public async Task AddReaction(AddReactionRequest request)
|
||||
{
|
||||
var command = new Vortex.Modules.Chats.Application.Messages.React.AddReactionCommand(
|
||||
request.MessageId, _userContext.UserId, request.Emoji, request.ChatId);
|
||||
await _sender.Send(command);
|
||||
}
|
||||
|
||||
[HubMethodName("remove_reaction")]
|
||||
public async Task RemoveReaction(RemoveReactionRequest request)
|
||||
{
|
||||
var command = new Vortex.Modules.Chats.Application.Messages.React.RemoveReactionCommand(
|
||||
request.MessageId, _userContext.UserId, request.Emoji, request.ChatId);
|
||||
await _sender.Send(command);
|
||||
}
|
||||
|
||||
// ────────────────────────────────────────────────────────────────
|
||||
// WebRTC signaling
|
||||
// ────────────────────────────────────────────────────────────────
|
||||
@@ -240,7 +259,15 @@ public sealed class ChatHub : Hub
|
||||
// Records
|
||||
// ────────────────────────────────────────────────────────────────
|
||||
|
||||
public record SendMessageHubRequest(Guid ChatId, string? Content, string Type, string? MediaUrl, string? MediaType, string? FileName, long? FileSize);
|
||||
public record AttachmentHubRequest(string Type, string Url, string? FileName, long? FileSize);
|
||||
public record SendMessageHubRequest(
|
||||
Guid ChatId,
|
||||
string? Content,
|
||||
string Type,
|
||||
List<AttachmentHubRequest>? Attachments = null,
|
||||
Guid? ReplyToId = null,
|
||||
string? Quote = null,
|
||||
Guid? ForwardedFromId = null);
|
||||
public record ReadMessagesRequest(Guid ChatId, List<string>? MessageIds);
|
||||
public record CallOfferRequest(string TargetUserId, object Offer, string CallType, string? ChatId);
|
||||
public record CallAnswerRequest(string TargetUserId, object Answer);
|
||||
@@ -249,4 +276,6 @@ public sealed class ChatHub : Hub
|
||||
public record RenegotiateRequest(string TargetUserId, object Offer);
|
||||
public record RenegotiateAnswerRequest(string TargetUserId, object Answer);
|
||||
public record CallTypeChangedRequest(string TargetUserId, string CallType);
|
||||
public record AddReactionRequest(Guid MessageId, Guid ChatId, string Emoji);
|
||||
public record RemoveReactionRequest(Guid MessageId, Guid ChatId, string Emoji);
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -13,7 +13,7 @@ using System.Reflection;
|
||||
[assembly: System.Reflection.AssemblyCompanyAttribute("Vortex.Modules.Chats")]
|
||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+50d4d75c04b5524c8439d9168f3a5a578f26d47c")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+d025c98e61cc08a53e6ebc62544d35be73a039e7")]
|
||||
[assembly: System.Reflection.AssemblyProductAttribute("Vortex.Modules.Chats")]
|
||||
[assembly: System.Reflection.AssemblyTitleAttribute("Vortex.Modules.Chats")]
|
||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||
|
||||
@@ -1 +1 @@
|
||||
7ea02b337752b6c3ee9972270dd51a0230d3bf7881178b777a5efe217aceafb1
|
||||
3f81474107c936fb7023dd1f1d41b8c6e04cc78e956d41fb0e98d29b21aae2c3
|
||||
|
||||
@@ -10,7 +10,7 @@ build_property.PlatformNeutralAssembly =
|
||||
build_property.EnforceExtendedAnalyzerRules =
|
||||
build_property._SupportedPlatformList = Linux,macOS,Windows
|
||||
build_property.RootNamespace = Vortex.Modules.Chats
|
||||
build_property.ProjectDir = E:\GIT\forkmessager\apps\server-net\src\Modules\Chats\
|
||||
build_property.ProjectDir = e:\GIT\forkmessager\apps\server-net\src\Modules\Chats\
|
||||
build_property.EnableComHosting =
|
||||
build_property.EnableGeneratedComInterfaceComImportInterop =
|
||||
build_property.EffectiveAnalysisLevelStyle = 10.0
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
||||
c39010166c2f8abf3397d023e78ad2aa480bef5668aa8c99f0daac981b2cf801
|
||||
361b9f18466c016bfc9d27e7847a8f24463479b03b82ec7866a1124dede24edb
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,17 +1,17 @@
|
||||
{
|
||||
"format": 1,
|
||||
"restore": {
|
||||
"E:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Chats\\Vortex.Modules.Chats.csproj": {}
|
||||
"e:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Chats\\Vortex.Modules.Chats.csproj": {}
|
||||
},
|
||||
"projects": {
|
||||
"E:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Chats\\Vortex.Modules.Chats.csproj": {
|
||||
"e:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Chats\\Vortex.Modules.Chats.csproj": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Chats\\Vortex.Modules.Chats.csproj",
|
||||
"projectUniqueName": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Chats\\Vortex.Modules.Chats.csproj",
|
||||
"projectName": "Vortex.Modules.Chats",
|
||||
"projectPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Chats\\Vortex.Modules.Chats.csproj",
|
||||
"projectPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Chats\\Vortex.Modules.Chats.csproj",
|
||||
"packagesPath": "C:\\Users\\HomePC\\.nuget\\packages\\",
|
||||
"outputPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Chats\\obj\\",
|
||||
"outputPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Chats\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
|
||||
@@ -33,8 +33,8 @@
|
||||
"net10.0": {
|
||||
"targetAlias": "net10.0",
|
||||
"projectReferences": {
|
||||
"E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj": {
|
||||
"projectPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj"
|
||||
"e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj": {
|
||||
"projectPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -518,14 +518,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj": {
|
||||
"e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj",
|
||||
"projectUniqueName": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj",
|
||||
"projectName": "Vortex.Shared.Kernel",
|
||||
"projectPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj",
|
||||
"projectPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj",
|
||||
"packagesPath": "C:\\Users\\HomePC\\.nuget\\packages\\",
|
||||
"outputPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\obj\\",
|
||||
"outputPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
|
||||
|
||||
@@ -785,11 +785,11 @@
|
||||
"project": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Chats\\Vortex.Modules.Chats.csproj",
|
||||
"projectUniqueName": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Chats\\Vortex.Modules.Chats.csproj",
|
||||
"projectName": "Vortex.Modules.Chats",
|
||||
"projectPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Chats\\Vortex.Modules.Chats.csproj",
|
||||
"projectPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Chats\\Vortex.Modules.Chats.csproj",
|
||||
"packagesPath": "C:\\Users\\HomePC\\.nuget\\packages\\",
|
||||
"outputPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Chats\\obj\\",
|
||||
"outputPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Chats\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
|
||||
@@ -811,8 +811,8 @@
|
||||
"net10.0": {
|
||||
"targetAlias": "net10.0",
|
||||
"projectReferences": {
|
||||
"E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj": {
|
||||
"projectPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj"
|
||||
"e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj": {
|
||||
"projectPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"version": 2,
|
||||
"dgSpecHash": "rWL1CDgJNu8=",
|
||||
"dgSpecHash": "TeczXo+31S0=",
|
||||
"success": true,
|
||||
"projectFilePath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Chats\\Vortex.Modules.Chats.csproj",
|
||||
"projectFilePath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Chats\\Vortex.Modules.Chats.csproj",
|
||||
"expectedPackageFiles": [
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\mediatr\\12.0.1\\mediatr.12.0.1.nupkg.sha512",
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\mediatr.contracts\\2.0.1\\mediatr.contracts.2.0.1.nupkg.sha512",
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -13,7 +13,7 @@ using System.Reflection;
|
||||
[assembly: System.Reflection.AssemblyCompanyAttribute("Vortex.Modules.Identity")]
|
||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+50d4d75c04b5524c8439d9168f3a5a578f26d47c")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+d025c98e61cc08a53e6ebc62544d35be73a039e7")]
|
||||
[assembly: System.Reflection.AssemblyProductAttribute("Vortex.Modules.Identity")]
|
||||
[assembly: System.Reflection.AssemblyTitleAttribute("Vortex.Modules.Identity")]
|
||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||
|
||||
@@ -1 +1 @@
|
||||
59b2bed890c47b7093a9de6a348a05d0adb9ad9b7fdd786efe67aaec3a83cae8
|
||||
c3cadb6f052217ce8055d22cc45365823011381722fc02323060802003a463fa
|
||||
|
||||
@@ -10,7 +10,7 @@ build_property.PlatformNeutralAssembly =
|
||||
build_property.EnforceExtendedAnalyzerRules =
|
||||
build_property._SupportedPlatformList = Linux,macOS,Windows
|
||||
build_property.RootNamespace = Vortex.Modules.Identity
|
||||
build_property.ProjectDir = E:\GIT\forkmessager\apps\server-net\src\Modules\Identity\
|
||||
build_property.ProjectDir = e:\GIT\forkmessager\apps\server-net\src\Modules\Identity\
|
||||
build_property.EnableComHosting =
|
||||
build_property.EnableGeneratedComInterfaceComImportInterop =
|
||||
build_property.EffectiveAnalysisLevelStyle = 10.0
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,17 +1,17 @@
|
||||
{
|
||||
"format": 1,
|
||||
"restore": {
|
||||
"E:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Identity\\Vortex.Modules.Identity.csproj": {}
|
||||
"e:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Identity\\Vortex.Modules.Identity.csproj": {}
|
||||
},
|
||||
"projects": {
|
||||
"E:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Identity\\Vortex.Modules.Identity.csproj": {
|
||||
"e:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Identity\\Vortex.Modules.Identity.csproj": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Identity\\Vortex.Modules.Identity.csproj",
|
||||
"projectUniqueName": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Identity\\Vortex.Modules.Identity.csproj",
|
||||
"projectName": "Vortex.Modules.Identity",
|
||||
"projectPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Identity\\Vortex.Modules.Identity.csproj",
|
||||
"projectPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Identity\\Vortex.Modules.Identity.csproj",
|
||||
"packagesPath": "C:\\Users\\HomePC\\.nuget\\packages\\",
|
||||
"outputPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Identity\\obj\\",
|
||||
"outputPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Identity\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
|
||||
@@ -33,8 +33,8 @@
|
||||
"net10.0": {
|
||||
"targetAlias": "net10.0",
|
||||
"projectReferences": {
|
||||
"E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj": {
|
||||
"projectPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj"
|
||||
"e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj": {
|
||||
"projectPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -534,14 +534,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj": {
|
||||
"e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj",
|
||||
"projectUniqueName": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj",
|
||||
"projectName": "Vortex.Shared.Kernel",
|
||||
"projectPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj",
|
||||
"projectPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj",
|
||||
"packagesPath": "C:\\Users\\HomePC\\.nuget\\packages\\",
|
||||
"outputPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\obj\\",
|
||||
"outputPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
|
||||
|
||||
@@ -1201,11 +1201,11 @@
|
||||
"project": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Identity\\Vortex.Modules.Identity.csproj",
|
||||
"projectUniqueName": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Identity\\Vortex.Modules.Identity.csproj",
|
||||
"projectName": "Vortex.Modules.Identity",
|
||||
"projectPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Identity\\Vortex.Modules.Identity.csproj",
|
||||
"projectPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Identity\\Vortex.Modules.Identity.csproj",
|
||||
"packagesPath": "C:\\Users\\HomePC\\.nuget\\packages\\",
|
||||
"outputPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Identity\\obj\\",
|
||||
"outputPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Identity\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
|
||||
@@ -1227,8 +1227,8 @@
|
||||
"net10.0": {
|
||||
"targetAlias": "net10.0",
|
||||
"projectReferences": {
|
||||
"E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj": {
|
||||
"projectPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj"
|
||||
"e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj": {
|
||||
"projectPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"version": 2,
|
||||
"dgSpecHash": "zJhKnu5UrIw=",
|
||||
"dgSpecHash": "LFvHqUy/0DQ=",
|
||||
"success": true,
|
||||
"projectFilePath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Identity\\Vortex.Modules.Identity.csproj",
|
||||
"projectFilePath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Identity\\Vortex.Modules.Identity.csproj",
|
||||
"expectedPackageFiles": [
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\bcrypt.net-next\\4.1.0\\bcrypt.net-next.4.1.0.nupkg.sha512",
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\mediatr\\12.0.1\\mediatr.12.0.1.nupkg.sha512",
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Vortex.Shared.Infrastructure.Middleware;
|
||||
|
||||
public sealed class ExceptionHandlingMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly ILogger<ExceptionHandlingMiddleware> _logger;
|
||||
|
||||
public ExceptionHandlingMiddleware(RequestDelegate next, ILogger<ExceptionHandlingMiddleware> logger)
|
||||
{
|
||||
_next = next;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task InvokeAsync(HttpContext context)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _next(context);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "An unhandled exception has occurred.");
|
||||
await HandleExceptionAsync(context, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task HandleExceptionAsync(HttpContext context, Exception exception)
|
||||
{
|
||||
context.Response.ContentType = "application/json";
|
||||
|
||||
var (statusCode, message) = exception switch
|
||||
{
|
||||
UnauthorizedAccessException => (HttpStatusCode.Unauthorized, "Unauthorized access."),
|
||||
KeyNotFoundException => (HttpStatusCode.NotFound, "Resource not found."),
|
||||
InvalidOperationException => (HttpStatusCode.BadRequest, exception.Message),
|
||||
_ => (HttpStatusCode.InternalServerError, "An internal server error occurred.")
|
||||
};
|
||||
|
||||
context.Response.StatusCode = (int)statusCode;
|
||||
|
||||
var response = new
|
||||
{
|
||||
message = message,
|
||||
error = message,
|
||||
detail = exception.Message,
|
||||
status = context.Response.StatusCode
|
||||
};
|
||||
|
||||
await context.Response.WriteAsync(JsonSerializer.Serialize(response, new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||||
}));
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -13,7 +13,7 @@ using System.Reflection;
|
||||
[assembly: System.Reflection.AssemblyCompanyAttribute("Vortex.Shared.Infrastructure")]
|
||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+50d4d75c04b5524c8439d9168f3a5a578f26d47c")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+d025c98e61cc08a53e6ebc62544d35be73a039e7")]
|
||||
[assembly: System.Reflection.AssemblyProductAttribute("Vortex.Shared.Infrastructure")]
|
||||
[assembly: System.Reflection.AssemblyTitleAttribute("Vortex.Shared.Infrastructure")]
|
||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||
|
||||
@@ -1 +1 @@
|
||||
df12f6b69987ce482a3bc4baa321fe1724bb58d2f9dd614e6cb5e69e22c189a3
|
||||
adb7ba56083ad67b90d8f8374db47603dfc37300aa26f470695f98b925535a7f
|
||||
|
||||
@@ -10,7 +10,7 @@ build_property.PlatformNeutralAssembly =
|
||||
build_property.EnforceExtendedAnalyzerRules =
|
||||
build_property._SupportedPlatformList = Linux,macOS,Windows
|
||||
build_property.RootNamespace = Vortex.Shared.Infrastructure
|
||||
build_property.ProjectDir = E:\GIT\forkmessager\apps\server-net\src\Shared\Vortex.Shared.Infrastructure\
|
||||
build_property.ProjectDir = e:\GIT\forkmessager\apps\server-net\src\Shared\Vortex.Shared.Infrastructure\
|
||||
build_property.EnableComHosting =
|
||||
build_property.EnableGeneratedComInterfaceComImportInterop =
|
||||
build_property.EffectiveAnalysisLevelStyle = 10.0
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
||||
ea74af991932cc803d3e09e69b37a4257b9120e69242a97360be1abe5a5d1ad5
|
||||
97c7b7e62856d30ecc962f5c969927254da81ac762aa00c7fb151631264e6936
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,17 +1,17 @@
|
||||
{
|
||||
"format": 1,
|
||||
"restore": {
|
||||
"E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Infrastructure\\Vortex.Shared.Infrastructure.csproj": {}
|
||||
"e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Infrastructure\\Vortex.Shared.Infrastructure.csproj": {}
|
||||
},
|
||||
"projects": {
|
||||
"E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Infrastructure\\Vortex.Shared.Infrastructure.csproj": {
|
||||
"e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Infrastructure\\Vortex.Shared.Infrastructure.csproj": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Infrastructure\\Vortex.Shared.Infrastructure.csproj",
|
||||
"projectUniqueName": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Infrastructure\\Vortex.Shared.Infrastructure.csproj",
|
||||
"projectName": "Vortex.Shared.Infrastructure",
|
||||
"projectPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Infrastructure\\Vortex.Shared.Infrastructure.csproj",
|
||||
"projectPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Infrastructure\\Vortex.Shared.Infrastructure.csproj",
|
||||
"packagesPath": "C:\\Users\\HomePC\\.nuget\\packages\\",
|
||||
"outputPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Infrastructure\\obj\\",
|
||||
"outputPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Infrastructure\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
|
||||
@@ -33,8 +33,8 @@
|
||||
"net10.0": {
|
||||
"targetAlias": "net10.0",
|
||||
"projectReferences": {
|
||||
"E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj": {
|
||||
"projectPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj"
|
||||
"e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj": {
|
||||
"projectPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -510,14 +510,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj": {
|
||||
"e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj",
|
||||
"projectUniqueName": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj",
|
||||
"projectName": "Vortex.Shared.Kernel",
|
||||
"projectPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj",
|
||||
"projectPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj",
|
||||
"packagesPath": "C:\\Users\\HomePC\\.nuget\\packages\\",
|
||||
"outputPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\obj\\",
|
||||
"outputPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
|
||||
|
||||
@@ -992,11 +992,11 @@
|
||||
"project": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Infrastructure\\Vortex.Shared.Infrastructure.csproj",
|
||||
"projectUniqueName": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Infrastructure\\Vortex.Shared.Infrastructure.csproj",
|
||||
"projectName": "Vortex.Shared.Infrastructure",
|
||||
"projectPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Infrastructure\\Vortex.Shared.Infrastructure.csproj",
|
||||
"projectPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Infrastructure\\Vortex.Shared.Infrastructure.csproj",
|
||||
"packagesPath": "C:\\Users\\HomePC\\.nuget\\packages\\",
|
||||
"outputPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Infrastructure\\obj\\",
|
||||
"outputPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Infrastructure\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
|
||||
@@ -1018,8 +1018,8 @@
|
||||
"net10.0": {
|
||||
"targetAlias": "net10.0",
|
||||
"projectReferences": {
|
||||
"E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj": {
|
||||
"projectPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj"
|
||||
"e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj": {
|
||||
"projectPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"version": 2,
|
||||
"dgSpecHash": "+h84t9fYbLg=",
|
||||
"dgSpecHash": "mujERCxuDP8=",
|
||||
"success": true,
|
||||
"projectFilePath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Infrastructure\\Vortex.Shared.Infrastructure.csproj",
|
||||
"projectFilePath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Infrastructure\\Vortex.Shared.Infrastructure.csproj",
|
||||
"expectedPackageFiles": [
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\mediatr\\12.0.1\\mediatr.12.0.1.nupkg.sha512",
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\mediatr.contracts\\2.0.1\\mediatr.contracts.2.0.1.nupkg.sha512",
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -13,7 +13,7 @@ using System.Reflection;
|
||||
[assembly: System.Reflection.AssemblyCompanyAttribute("Vortex.Shared.Kernel")]
|
||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+50d4d75c04b5524c8439d9168f3a5a578f26d47c")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+d025c98e61cc08a53e6ebc62544d35be73a039e7")]
|
||||
[assembly: System.Reflection.AssemblyProductAttribute("Vortex.Shared.Kernel")]
|
||||
[assembly: System.Reflection.AssemblyTitleAttribute("Vortex.Shared.Kernel")]
|
||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||
|
||||
@@ -1 +1 @@
|
||||
3df2ff458195b9e6584b2fb1c283dc45733b10adf112306fa915e3c17fd69248
|
||||
2ab218fedb325bf279a8607f3ddd12468bb20cfa3895570bcfa7cdb1e276425f
|
||||
|
||||
@@ -10,7 +10,7 @@ build_property.PlatformNeutralAssembly =
|
||||
build_property.EnforceExtendedAnalyzerRules =
|
||||
build_property._SupportedPlatformList = Linux,macOS,Windows
|
||||
build_property.RootNamespace = Vortex.Shared.Kernel
|
||||
build_property.ProjectDir = E:\GIT\forkmessager\apps\server-net\src\Shared\Vortex.Shared.Kernel\
|
||||
build_property.ProjectDir = e:\GIT\forkmessager\apps\server-net\src\Shared\Vortex.Shared.Kernel\
|
||||
build_property.EnableComHosting =
|
||||
build_property.EnableGeneratedComInterfaceComImportInterop =
|
||||
build_property.EffectiveAnalysisLevelStyle = 10.0
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,17 +1,17 @@
|
||||
{
|
||||
"format": 1,
|
||||
"restore": {
|
||||
"E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj": {}
|
||||
"e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj": {}
|
||||
},
|
||||
"projects": {
|
||||
"E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj": {
|
||||
"e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj",
|
||||
"projectUniqueName": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj",
|
||||
"projectName": "Vortex.Shared.Kernel",
|
||||
"projectPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj",
|
||||
"projectPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj",
|
||||
"packagesPath": "C:\\Users\\HomePC\\.nuget\\packages\\",
|
||||
"outputPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\obj\\",
|
||||
"outputPath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"version": 2,
|
||||
"dgSpecHash": "qfmzINr+8lA=",
|
||||
"dgSpecHash": "SdDYXwY4FZU=",
|
||||
"success": true,
|
||||
"projectFilePath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj",
|
||||
"projectFilePath": "e:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj",
|
||||
"expectedPackageFiles": [
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\mediatr\\12.0.1\\mediatr.12.0.1.nupkg.sha512",
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\mediatr.contracts\\2.0.1\\mediatr.contracts.2.0.1.nupkg.sha512",
|
||||
|
||||
@@ -30,37 +30,74 @@ public sealed class MessagesController : ControllerBase
|
||||
{
|
||||
var messages = await messageRepository.GetChatMessagesAsync(chatId, 50, 0, ct);
|
||||
|
||||
// Получаем всех уникальных отправителей
|
||||
var senderIds = messages.Select(m => m.SenderId).Distinct().ToList();
|
||||
// Collect all user IDs needed (senders, forwarded from)
|
||||
var userIds = messages.Select(m => m.SenderId).ToList();
|
||||
userIds.AddRange(messages.Where(m => m.ForwardedFromId.HasValue).Select(m => m.ForwardedFromId!.Value));
|
||||
|
||||
var senders = new Dictionary<Guid, Vortex.Modules.Identity.Domain.User>();
|
||||
foreach (var id in senderIds)
|
||||
foreach (var id in userIds.Distinct())
|
||||
{
|
||||
var user = await _userRepository.GetByIdAsync(id, ct);
|
||||
if (user != null) senders[id] = user;
|
||||
}
|
||||
|
||||
var result = messages.Select(m => new
|
||||
var result = new List<object>();
|
||||
foreach (var m in messages)
|
||||
{
|
||||
m.Id,
|
||||
m.ChatId,
|
||||
m.SenderId,
|
||||
m.Content,
|
||||
m.Type,
|
||||
m.ReplyToId,
|
||||
m.Quote,
|
||||
m.IsEdited,
|
||||
m.IsDeleted,
|
||||
m.CreatedAt,
|
||||
Media = m.Media.ToList(),
|
||||
Sender = senders.TryGetValue(m.SenderId, out var s) ? new {
|
||||
id = s.Id,
|
||||
username = s.Username,
|
||||
displayName = s.DisplayName,
|
||||
avatar = s.Avatar
|
||||
} : new { id = m.SenderId, username = "unknown", displayName = "Unknown", avatar = (string?)null },
|
||||
Reactions = new List<object>(),
|
||||
ReadBy = m.ReadBy.Select(r => new { userId = r.UserId }).ToList()
|
||||
});
|
||||
object? replyToObj = null;
|
||||
if (m.ReplyToId.HasValue)
|
||||
{
|
||||
var replyMsg = await messageRepository.GetByIdAsync(m.ReplyToId.Value, ct);
|
||||
if (replyMsg != null)
|
||||
{
|
||||
var replySender = await _userRepository.GetByIdAsync(replyMsg.SenderId, ct);
|
||||
replyToObj = new
|
||||
{
|
||||
id = replyMsg.Id,
|
||||
content = replyMsg.Content,
|
||||
media = replyMsg.Media.Select(rm => new { rm.Id, rm.Type, rm.Url }).ToList(),
|
||||
sender = replySender != null ? new { id = replySender.Id, username = replySender.Username, displayName = replySender.DisplayName } : null
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
result.Add(new
|
||||
{
|
||||
m.Id,
|
||||
m.ChatId,
|
||||
m.SenderId,
|
||||
m.Content,
|
||||
m.Type,
|
||||
m.ReplyToId,
|
||||
replyTo = replyToObj,
|
||||
m.Quote,
|
||||
m.IsEdited,
|
||||
m.IsDeleted,
|
||||
m.CreatedAt,
|
||||
forwardedFromId = m.ForwardedFromId,
|
||||
forwardedFrom = m.ForwardedFromId.HasValue && senders.TryGetValue(m.ForwardedFromId.Value, out var fwd) ? new {
|
||||
id = fwd.Id,
|
||||
username = fwd.Username,
|
||||
displayName = fwd.DisplayName,
|
||||
avatar = fwd.Avatar
|
||||
} : null,
|
||||
media = m.Media.Select(media => new {
|
||||
media.Id,
|
||||
media.Type,
|
||||
media.Url,
|
||||
filename = media.Filename,
|
||||
size = media.Size
|
||||
}).ToList(),
|
||||
sender = senders.TryGetValue(m.SenderId, out var s) ? new {
|
||||
id = s.Id,
|
||||
username = s.Username,
|
||||
displayName = s.DisplayName,
|
||||
avatar = s.Avatar
|
||||
} : new { id = m.SenderId, username = "unknown", displayName = "Unknown", avatar = (string?)null },
|
||||
reactions = m.Reactions.Select(r => new { r.UserId, r.Emoji }).ToList(),
|
||||
readBy = m.ReadBy.Select(r => new { userId = r.UserId }).ToList()
|
||||
});
|
||||
}
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
@@ -70,9 +107,11 @@ public sealed class MessagesController : ControllerBase
|
||||
{
|
||||
var messages = await messageRepository.SearchMessagesAsync(q, chatId, ct);
|
||||
|
||||
var senderIds = messages.Select(m => m.SenderId).Distinct().ToList();
|
||||
var userIds = messages.Select(m => m.SenderId).ToList();
|
||||
userIds.AddRange(messages.Where(m => m.ForwardedFromId.HasValue).Select(m => m.ForwardedFromId!.Value));
|
||||
|
||||
var senders = new Dictionary<Guid, Vortex.Modules.Identity.Domain.User>();
|
||||
foreach (var id in senderIds)
|
||||
foreach (var id in userIds.Distinct())
|
||||
{
|
||||
var user = await _userRepository.GetByIdAsync(id, ct);
|
||||
if (user != null) senders[id] = user;
|
||||
@@ -90,15 +129,28 @@ public sealed class MessagesController : ControllerBase
|
||||
m.IsEdited,
|
||||
m.IsDeleted,
|
||||
m.CreatedAt,
|
||||
Media = m.Media.ToList(),
|
||||
Sender = senders.TryGetValue(m.SenderId, out var s) ? new {
|
||||
forwardedFromId = m.ForwardedFromId,
|
||||
forwardedFrom = m.ForwardedFromId.HasValue && senders.TryGetValue(m.ForwardedFromId.Value, out var fwd) ? new {
|
||||
id = fwd.Id,
|
||||
username = fwd.Username,
|
||||
displayName = fwd.DisplayName,
|
||||
avatar = fwd.Avatar
|
||||
} : null,
|
||||
media = m.Media.Select(media => new {
|
||||
media.Id,
|
||||
media.Type,
|
||||
media.Url,
|
||||
filename = media.Filename,
|
||||
size = media.Size
|
||||
}).ToList(),
|
||||
sender = senders.TryGetValue(m.SenderId, out var s) ? new {
|
||||
id = s.Id,
|
||||
username = s.Username,
|
||||
displayName = s.DisplayName,
|
||||
avatar = s.Avatar
|
||||
} : new { id = m.SenderId, username = "unknown", displayName = "Unknown", avatar = (string?)null },
|
||||
Reactions = new List<object>(),
|
||||
ReadBy = m.ReadBy.Select(r => new { userId = r.UserId }).ToList()
|
||||
reactions = m.Reactions.Select(r => new { r.UserId, r.Emoji }).ToList(),
|
||||
readBy = m.ReadBy.Select(r => new { userId = r.UserId }).ToList()
|
||||
});
|
||||
|
||||
return Ok(result);
|
||||
@@ -126,7 +178,19 @@ public sealed class MessagesController : ControllerBase
|
||||
[HttpPost("chat/{chatId:guid}")]
|
||||
public async Task<IActionResult> SendMessage(Guid chatId, [FromBody] SendMessageRequest request)
|
||||
{
|
||||
var command = new SendMessageCommand(chatId, _userContext.UserId, request.Content, request.Type);
|
||||
var attachments = request.Attachments?.Select(a =>
|
||||
new Vortex.Modules.Chats.Application.Messages.Send.AttachmentRequest(a.Type, a.Url, a.FileName, a.FileSize)).ToList();
|
||||
|
||||
var command = new SendMessageCommand(
|
||||
chatId,
|
||||
_userContext.UserId,
|
||||
request.Content,
|
||||
request.Type,
|
||||
attachments,
|
||||
request.ReplyToId,
|
||||
request.Quote,
|
||||
request.ForwardedFromId);
|
||||
|
||||
Result<Guid> result = await _sender.Send(command);
|
||||
|
||||
if (result.IsFailure)
|
||||
@@ -138,4 +202,12 @@ public sealed class MessagesController : ControllerBase
|
||||
}
|
||||
}
|
||||
|
||||
public sealed record SendMessageRequest(string Content, string Type);
|
||||
public sealed record SendMessageRequest(
|
||||
string? Content,
|
||||
string Type,
|
||||
List<AttachmentDto>? Attachments = null,
|
||||
Guid? ReplyToId = null,
|
||||
string? Quote = null,
|
||||
Guid? ForwardedFromId = null);
|
||||
|
||||
public sealed record AttachmentDto(string Type, string Url, string? FileName, long? FileSize);
|
||||
|
||||
@@ -18,6 +18,23 @@ JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Регистрация модулей
|
||||
// Маппинг стандартных переменных окружения в иерархию .NET
|
||||
var envMappings = new Dictionary<string, string?>
|
||||
{
|
||||
["ConnectionStrings:Database"] = builder.Configuration["DATABASE_URL"],
|
||||
["Jwt:Secret"] = builder.Configuration["JWT_SECRET"],
|
||||
["Jwt:Issuer"] = builder.Configuration["JWT_ISSUER"],
|
||||
["Jwt:Audience"] = builder.Configuration["JWT_AUDIENCE"],
|
||||
["WebRtc:TurnUrl"] = builder.Configuration["TURN_URL"],
|
||||
["WebRtc:TurnUsername"] = builder.Configuration["TURN_USERNAME"],
|
||||
["WebRtc:TurnPassword"] = builder.Configuration["TURN_PASSWORD"]
|
||||
};
|
||||
|
||||
// Добавляем только те, что реально заданы в ENV
|
||||
builder.Configuration.AddInMemoryCollection(
|
||||
envMappings.Where(kv => !string.IsNullOrEmpty(kv.Value))
|
||||
.ToDictionary(kv => kv.Key, kv => kv.Value));
|
||||
|
||||
builder.Services.AddIdentityModule(builder.Configuration);
|
||||
builder.Services.AddChatsModule(builder.Configuration);
|
||||
builder.Services.AddSharedInfrastructure();
|
||||
@@ -93,6 +110,8 @@ using (var scope = app.Services.CreateScope())
|
||||
}
|
||||
|
||||
// Настройка конвейера запросов
|
||||
app.UseMiddleware<Vortex.Shared.Infrastructure.Middleware.ExceptionHandlingMiddleware>();
|
||||
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseSwagger();
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -13,7 +13,7 @@ using System.Reflection;
|
||||
[assembly: System.Reflection.AssemblyCompanyAttribute("Vortex.Host")]
|
||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+50d4d75c04b5524c8439d9168f3a5a578f26d47c")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+d025c98e61cc08a53e6ebc62544d35be73a039e7")]
|
||||
[assembly: System.Reflection.AssemblyProductAttribute("Vortex.Host")]
|
||||
[assembly: System.Reflection.AssemblyTitleAttribute("Vortex.Host")]
|
||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||
|
||||
@@ -1 +1 @@
|
||||
d03092ba384d8502d5f7fd21d156b23d210e0799f76ba7d21d44c4557e61517a
|
||||
7eb1f40e06ff22545aecfb70096f70b5f91da82514bc2bf01247c568eaabc058
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
cc44608f02d3c58ef2ef3a01f7beeb9810e26622a8244a47488abc4fe1fba02e
|
||||
11d26d1b87f3679d8be8eeb05168fa71c45a3d83b12aa28eb232183b34639103
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
||||
{"GlobalPropertiesHash":"2XkPbXFkjVRjCUBTJbQq8CDd7pjsUOS1j3gPHS73xDA=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["uOUIBvk7jdHp7c93RIuECwNykpOmiZnVmQxETsngeR0=","ToV71GGCtcAptkaGqQYXeNtDQnAJEljvYAkAKnIRZ\u002Bs=","2fjU\u002BjCBiHEuKj2uQgoWti0oZXkpAdICFty/O9cJSyc=","aTLUi985DoL1wb7QmuhiHoO7J3hi30WEVAUbYVkXxss=","M2rU4lkbWHA97xrUqDaBg8DOdPjKImLmDLqxa\u002BEOspY="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||
{"GlobalPropertiesHash":"2XkPbXFkjVRjCUBTJbQq8CDd7pjsUOS1j3gPHS73xDA=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["uOUIBvk7jdHp7c93RIuECwNykpOmiZnVmQxETsngeR0=","ToV71GGCtcAptkaGqQYXeNtDQnAJEljvYAkAKnIRZ\u002Bs=","2fjU\u002BjCBiHEuKj2uQgoWti0oZXkpAdICFty/O9cJSyc=","aTLUi985DoL1wb7QmuhiHoO7J3hi30WEVAUbYVkXxss=","j8oEy769HqBb/9GTCrDSdFySoPpImy4D0XnzBBTzsT0="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||
@@ -1 +1 @@
|
||||
{"GlobalPropertiesHash":"2L4HBRt/ChGO9rohi3wtSDqo95X47fme5m8OHgJIZL0=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["uOUIBvk7jdHp7c93RIuECwNykpOmiZnVmQxETsngeR0=","ToV71GGCtcAptkaGqQYXeNtDQnAJEljvYAkAKnIRZ\u002Bs=","2fjU\u002BjCBiHEuKj2uQgoWti0oZXkpAdICFty/O9cJSyc=","aTLUi985DoL1wb7QmuhiHoO7J3hi30WEVAUbYVkXxss=","M2rU4lkbWHA97xrUqDaBg8DOdPjKImLmDLqxa\u002BEOspY="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||
{"GlobalPropertiesHash":"2L4HBRt/ChGO9rohi3wtSDqo95X47fme5m8OHgJIZL0=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["uOUIBvk7jdHp7c93RIuECwNykpOmiZnVmQxETsngeR0=","ToV71GGCtcAptkaGqQYXeNtDQnAJEljvYAkAKnIRZ\u002Bs=","2fjU\u002BjCBiHEuKj2uQgoWti0oZXkpAdICFty/O9cJSyc=","aTLUi985DoL1wb7QmuhiHoO7J3hi30WEVAUbYVkXxss=","j8oEy769HqBb/9GTCrDSdFySoPpImy4D0XnzBBTzsT0="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user