🗑️ Remove imagesharp
This commit is contained in:
		| @@ -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); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user