🗑️ Remove imagesharp
This commit is contained in:
parent
205ccd66b3
commit
b40282e43a
@ -1,16 +1,12 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using tencentyun;
|
||||
|
||||
namespace DysonNetwork.Sphere.Chat;
|
||||
|
||||
public class RealtimeChatConfiguration
|
||||
{
|
||||
public string Provider { get; set; } = null!;
|
||||
public int AppId { get; set; }
|
||||
[JsonIgnore] public string SecretKey { get; set; } = null!;
|
||||
}
|
||||
|
||||
[ApiController]
|
||||
@ -20,46 +16,6 @@ public class RealtimeCallController(IConfiguration configuration, AppDatabase db
|
||||
private readonly RealtimeChatConfiguration _config =
|
||||
configuration.GetSection("RealtimeChat").Get<RealtimeChatConfiguration>()!;
|
||||
|
||||
[HttpGet]
|
||||
public ActionResult<RealtimeChatConfiguration> GetConfiguration()
|
||||
{
|
||||
return _config;
|
||||
}
|
||||
|
||||
public class RealtimeChatToken
|
||||
{
|
||||
public RealtimeChatConfiguration Config { get; set; } = null!;
|
||||
public string Token { get; set; } = null!;
|
||||
}
|
||||
|
||||
[HttpGet("{roomId:guid}")]
|
||||
[Authorize]
|
||||
public async Task<ActionResult<RealtimeChatToken>> GetToken(Guid roomId)
|
||||
{
|
||||
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized();
|
||||
|
||||
var member = await db.ChatMembers
|
||||
.Where(m => m.AccountId == currentUser.Id && m.ChatRoomId == roomId)
|
||||
.FirstOrDefaultAsync();
|
||||
if (member == null || member.Role < ChatMemberRole.Member)
|
||||
return StatusCode(403,
|
||||
"You need to be a normal member to get the token for joining the realtime chatroom."
|
||||
);
|
||||
|
||||
var ongoingCall = await cs.GetCallOngoingAsync(roomId);
|
||||
if (ongoingCall is null) return BadRequest("No ongoing call.");
|
||||
|
||||
var api = new TLSSigAPIv2(_config.AppId, _config.SecretKey);
|
||||
var sig = api.GenSig(currentUser.Name);
|
||||
if (sig is null) return StatusCode(500, "Failed to generate the token.");
|
||||
|
||||
return Ok(new RealtimeChatToken
|
||||
{
|
||||
Config = _config,
|
||||
Token = sig
|
||||
});
|
||||
}
|
||||
|
||||
[HttpPost("{roomId:guid}")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> StartCall(Guid roomId)
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
||||
<PackageReference Include="Blurhash.ImageSharp" Version="4.0.0" />
|
||||
<PackageReference Include="BlurHashSharp.SkiaSharp" Version="1.3.4" />
|
||||
<PackageReference Include="CorePush" Version="4.3.0" />
|
||||
<PackageReference Include="EFCore.BulkExtensions" Version="9.0.1" />
|
||||
<PackageReference Include="EFCore.BulkExtensions.PostgreSql" Version="9.0.1" />
|
||||
@ -58,12 +58,8 @@
|
||||
<PackageReference Include="Quartz" Version="3.14.0" />
|
||||
<PackageReference Include="Quartz.AspNetCore" Version="3.14.0" />
|
||||
<PackageReference Include="Quartz.Extensions.Hosting" Version="3.14.0" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.7" />
|
||||
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.5" />
|
||||
<PackageReference Include="SixLabors.ImageSharp.Web" Version="3.1.4" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="8.1.0" />
|
||||
<PackageReference Include="tls-sig-api-v2" Version="1.0.1" />
|
||||
<PackageReference Include="tusdotnet" Version="2.8.1" />
|
||||
</ItemGroup>
|
||||
|
||||
|
3386
DysonNetwork.Sphere/Migrations/20250518041519_OptimizeDataStructure.Designer.cs
generated
Normal file
3386
DysonNetwork.Sphere/Migrations/20250518041519_OptimizeDataStructure.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,103 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using NodaTime;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace DysonNetwork.Sphere.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class OptimizeDataStructure : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "chat_statuses");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "chat_read_receipts",
|
||||
columns: table => new
|
||||
{
|
||||
message_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
sender_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
|
||||
updated_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
|
||||
deleted_at = table.Column<Instant>(type: "timestamp with time zone", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_chat_read_receipts", x => new { x.message_id, x.sender_id });
|
||||
table.ForeignKey(
|
||||
name: "fk_chat_read_receipts_chat_members_sender_id",
|
||||
column: x => x.sender_id,
|
||||
principalTable: "chat_members",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_chat_read_receipts_chat_messages_message_id",
|
||||
column: x => x.message_id,
|
||||
principalTable: "chat_messages",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_chat_read_receipts_message_id_sender_id",
|
||||
table: "chat_read_receipts",
|
||||
columns: new[] { "message_id", "sender_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_chat_read_receipts_sender_id",
|
||||
table: "chat_read_receipts",
|
||||
column: "sender_id");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "chat_read_receipts");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "chat_statuses",
|
||||
columns: table => new
|
||||
{
|
||||
message_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
sender_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
|
||||
deleted_at = table.Column<Instant>(type: "timestamp with time zone", nullable: true),
|
||||
read_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
|
||||
updated_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_chat_statuses", x => new { x.message_id, x.sender_id });
|
||||
table.ForeignKey(
|
||||
name: "fk_chat_statuses_chat_members_sender_id",
|
||||
column: x => x.sender_id,
|
||||
principalTable: "chat_members",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_chat_statuses_chat_messages_message_id",
|
||||
column: x => x.message_id,
|
||||
principalTable: "chat_messages",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_chat_statuses_message_id_sender_id",
|
||||
table: "chat_statuses",
|
||||
columns: new[] { "message_id", "sender_id" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_chat_statuses_sender_id",
|
||||
table: "chat_statuses",
|
||||
column: "sender_id");
|
||||
}
|
||||
}
|
||||
}
|
@ -1143,7 +1143,7 @@ namespace DysonNetwork.Sphere.Migrations
|
||||
b.ToTable("chat_reactions", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("DysonNetwork.Sphere.Chat.MessageStatus", b =>
|
||||
modelBuilder.Entity("DysonNetwork.Sphere.Chat.MessageReadReceipt", b =>
|
||||
{
|
||||
b.Property<Guid>("MessageId")
|
||||
.HasColumnType("uuid")
|
||||
@ -1161,25 +1161,21 @@ namespace DysonNetwork.Sphere.Migrations
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("deleted_at");
|
||||
|
||||
b.Property<Instant>("ReadAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("read_at");
|
||||
|
||||
b.Property<Instant>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("updated_at");
|
||||
|
||||
b.HasKey("MessageId", "SenderId")
|
||||
.HasName("pk_chat_statuses");
|
||||
.HasName("pk_chat_read_receipts");
|
||||
|
||||
b.HasIndex("SenderId")
|
||||
.HasDatabaseName("ix_chat_statuses_sender_id");
|
||||
.HasDatabaseName("ix_chat_read_receipts_sender_id");
|
||||
|
||||
b.HasIndex("MessageId", "SenderId")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_chat_statuses_message_id_sender_id");
|
||||
.HasDatabaseName("ix_chat_read_receipts_message_id_sender_id");
|
||||
|
||||
b.ToTable("chat_statuses", (string)null);
|
||||
b.ToTable("chat_read_receipts", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("DysonNetwork.Sphere.Chat.RealtimeCall", b =>
|
||||
@ -2850,21 +2846,21 @@ namespace DysonNetwork.Sphere.Migrations
|
||||
b.Navigation("Sender");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("DysonNetwork.Sphere.Chat.MessageStatus", b =>
|
||||
modelBuilder.Entity("DysonNetwork.Sphere.Chat.MessageReadReceipt", b =>
|
||||
{
|
||||
b.HasOne("DysonNetwork.Sphere.Chat.Message", "Message")
|
||||
.WithMany("Statuses")
|
||||
.HasForeignKey("MessageId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("fk_chat_statuses_chat_messages_message_id");
|
||||
.HasConstraintName("fk_chat_read_receipts_chat_messages_message_id");
|
||||
|
||||
b.HasOne("DysonNetwork.Sphere.Chat.ChatMember", "Sender")
|
||||
.WithMany()
|
||||
.HasForeignKey("SenderId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("fk_chat_statuses_chat_members_sender_id");
|
||||
.HasConstraintName("fk_chat_read_receipts_chat_members_sender_id");
|
||||
|
||||
b.Navigation("Message");
|
||||
|
||||
|
@ -1,16 +1,12 @@
|
||||
using System.Globalization;
|
||||
using FFMpegCore;
|
||||
using System.Security.Cryptography;
|
||||
using Blurhash.ImageSharp;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Minio;
|
||||
using Minio.DataModel.Args;
|
||||
using NodaTime;
|
||||
using Quartz;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using SixLabors.ImageSharp.Metadata.Profiles.Exif;
|
||||
using tusdotnet.Stores;
|
||||
using ExifTag = SixLabors.ImageSharp.Metadata.Profiles.Exif.ExifTag;
|
||||
|
||||
namespace DysonNetwork.Sphere.Storage;
|
||||
|
||||
@ -53,32 +49,28 @@ public class FileService(
|
||||
switch (contentType.Split('/')[0])
|
||||
{
|
||||
case "image":
|
||||
var blurhash = BlurHashSharp.SkiaSharp.BlurHashEncoder.Encode(xComponent: 3, yComponent: 3, stream);
|
||||
|
||||
// Reset stream position after bitmap read
|
||||
stream.Position = 0;
|
||||
// We still need ImageSharp for blurhash calculation
|
||||
using (var imageSharp = await Image.LoadAsync<Rgba32>(stream))
|
||||
|
||||
// Use NetVips for the rest
|
||||
using (var vipsImage = NetVips.Image.NewFromStream(stream))
|
||||
{
|
||||
var blurhash = Blurhasher.Encode(imageSharp, 3, 3);
|
||||
|
||||
// Reset stream position after ImageSharp read
|
||||
stream.Position = 0;
|
||||
|
||||
// Use NetVips for the rest
|
||||
using var vipsImage = NetVips.Image.NewFromStream(stream);
|
||||
|
||||
var width = vipsImage.Width;
|
||||
var height = vipsImage.Height;
|
||||
var format = vipsImage.Get("vips-loader") ?? "unknown";
|
||||
|
||||
// Try to get orientation from exif data
|
||||
ushort orientation = 1;
|
||||
List<IExifValue> exif = [];
|
||||
Dictionary<string, object> exif = [];
|
||||
|
||||
// NetVips supports reading exif with vipsImage.GetField("exif-ifd0-Orientation")
|
||||
// but we'll keep the ImageSharp exif handling for now
|
||||
var exifProfile = imageSharp.Metadata.ExifProfile;
|
||||
if (exifProfile?.Values.FirstOrDefault(e => e.Tag == ExifTag.Orientation)
|
||||
?.GetValue() is ushort o)
|
||||
orientation = o;
|
||||
foreach (var field in vipsImage.GetFields())
|
||||
{
|
||||
var value = vipsImage.Get(field);
|
||||
exif.Add(field, value);
|
||||
if (field == "orientation") orientation = (ushort)value;
|
||||
}
|
||||
|
||||
if (orientation is 6 or 8)
|
||||
(width, height) = (height, width);
|
||||
|
Loading…
x
Reference in New Issue
Block a user