✨ Sticker icon
This commit is contained in:
@@ -38,7 +38,7 @@ public class SnCustomApp : ModelBase, IIdentifiedResource
|
|||||||
[NotMapped]
|
[NotMapped]
|
||||||
public SnDeveloper Developer => Project.Developer;
|
public SnDeveloper Developer => Project.Developer;
|
||||||
|
|
||||||
[NotMapped] public string ResourceIdentifier => "custom-app:" + Id;
|
[NotMapped] public string ResourceIdentifier => "developer.app:" + Id;
|
||||||
|
|
||||||
public Proto.CustomApp ToProto()
|
public Proto.CustomApp ToProto()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -50,5 +50,5 @@ public class FilePool : ModelBase, IIdentifiedResource
|
|||||||
|
|
||||||
public Guid? AccountId { get; set; }
|
public Guid? AccountId { get; set; }
|
||||||
|
|
||||||
public string ResourceIdentifier => $"file-pool/{Id}";
|
public string ResourceIdentifier => $"file.pool:{Id}";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,47 +11,33 @@ public class SnSticker : ModelBase, IIdentifiedResource
|
|||||||
{
|
{
|
||||||
public Guid Id { get; set; } = Guid.NewGuid();
|
public Guid Id { get; set; } = Guid.NewGuid();
|
||||||
|
|
||||||
[MaxLength(128)]
|
[MaxLength(128)] public string Slug { get; set; } = null!;
|
||||||
public string Slug { get; set; } = null!;
|
[Column(TypeName = "jsonb")] public SnCloudFileReferenceObject Image { get; set; } = null!;
|
||||||
|
|
||||||
// Outdated fields, for backward compability
|
|
||||||
[MaxLength(32)]
|
|
||||||
public string? ImageId { get; set; }
|
|
||||||
|
|
||||||
[Column(TypeName = "jsonb")]
|
|
||||||
public SnCloudFileReferenceObject? Image { get; set; } = null!;
|
|
||||||
|
|
||||||
public Guid PackId { get; set; }
|
public Guid PackId { get; set; }
|
||||||
|
[IgnoreMember] [JsonIgnore] public StickerPack Pack { get; set; } = null!;
|
||||||
|
|
||||||
[JsonIgnore]
|
public string ResourceIdentifier => $"sticker:{Id}";
|
||||||
public StickerPack Pack { get; set; } = null!;
|
|
||||||
|
|
||||||
public string ResourceIdentifier => $"sticker/{Id}";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Index(nameof(Prefix), IsUnique = true)]
|
[Index(nameof(Prefix), IsUnique = true)]
|
||||||
public class StickerPack : ModelBase
|
public class StickerPack : ModelBase, IIdentifiedResource
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; } = Guid.NewGuid();
|
public Guid Id { get; set; } = Guid.NewGuid();
|
||||||
|
|
||||||
[MaxLength(1024)]
|
[Column(TypeName = "jsonb")] public SnCloudFileReferenceObject? Icon { get; set; }
|
||||||
public string Name { get; set; } = null!;
|
[MaxLength(1024)] public string Name { get; set; } = null!;
|
||||||
|
[MaxLength(4096)] public string Description { get; set; } = string.Empty;
|
||||||
|
[MaxLength(128)] public string Prefix { get; set; } = null!;
|
||||||
|
|
||||||
[MaxLength(4096)]
|
|
||||||
public string Description { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
[MaxLength(128)]
|
|
||||||
public string Prefix { get; set; } = null!;
|
|
||||||
|
|
||||||
[IgnoreMember]
|
|
||||||
public List<SnSticker> Stickers { get; set; } = [];
|
public List<SnSticker> Stickers { get; set; } = [];
|
||||||
|
|
||||||
[IgnoreMember]
|
[IgnoreMember] [JsonIgnore] public List<StickerPackOwnership> Ownerships { get; set; } = [];
|
||||||
[JsonIgnore]
|
|
||||||
public List<StickerPackOwnership> Ownerships { get; set; } = [];
|
|
||||||
|
|
||||||
public Guid PublisherId { get; set; }
|
public Guid PublisherId { get; set; }
|
||||||
public SnPublisher Publisher { get; set; } = null!;
|
public SnPublisher Publisher { get; set; } = null!;
|
||||||
|
|
||||||
|
public string ResourceIdentifier => $"sticker.pack:{Id}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public class StickerPackOwnership : ModelBase
|
public class StickerPackOwnership : ModelBase
|
||||||
@@ -62,6 +48,5 @@ public class StickerPackOwnership : ModelBase
|
|||||||
public StickerPack Pack { get; set; } = null!;
|
public StickerPack Pack { get; set; } = null!;
|
||||||
public Guid AccountId { get; set; }
|
public Guid AccountId { get; set; }
|
||||||
|
|
||||||
[NotMapped]
|
[NotMapped] public SnAccount Account { get; set; } = null!;
|
||||||
public SnAccount Account { get; set; } = null!;
|
|
||||||
}
|
}
|
||||||
@@ -1147,14 +1147,10 @@ namespace DysonNetwork.Sphere.Migrations
|
|||||||
.HasColumnName("deleted_at");
|
.HasColumnName("deleted_at");
|
||||||
|
|
||||||
b.Property<SnCloudFileReferenceObject>("Image")
|
b.Property<SnCloudFileReferenceObject>("Image")
|
||||||
|
.IsRequired()
|
||||||
.HasColumnType("jsonb")
|
.HasColumnType("jsonb")
|
||||||
.HasColumnName("image");
|
.HasColumnName("image");
|
||||||
|
|
||||||
b.Property<string>("ImageId")
|
|
||||||
.HasMaxLength(32)
|
|
||||||
.HasColumnType("character varying(32)")
|
|
||||||
.HasColumnName("image_id");
|
|
||||||
|
|
||||||
b.Property<Guid>("PackId")
|
b.Property<Guid>("PackId")
|
||||||
.HasColumnType("uuid")
|
.HasColumnType("uuid")
|
||||||
.HasColumnName("pack_id");
|
.HasColumnName("pack_id");
|
||||||
@@ -1202,6 +1198,10 @@ namespace DysonNetwork.Sphere.Migrations
|
|||||||
.HasColumnType("character varying(4096)")
|
.HasColumnType("character varying(4096)")
|
||||||
.HasColumnName("description");
|
.HasColumnName("description");
|
||||||
|
|
||||||
|
b.Property<SnCloudFileReferenceObject>("Icon")
|
||||||
|
.HasColumnType("jsonb")
|
||||||
|
.HasColumnName("icon");
|
||||||
|
|
||||||
b.Property<string>("Name")
|
b.Property<string>("Name")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasMaxLength(1024)
|
.HasMaxLength(1024)
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ public class StickerController(
|
|||||||
AppDatabase db,
|
AppDatabase db,
|
||||||
StickerService st,
|
StickerService st,
|
||||||
Publisher.PublisherService ps,
|
Publisher.PublisherService ps,
|
||||||
FileService.FileServiceClient files
|
FileService.FileServiceClient files,
|
||||||
|
FileReferenceService.FileReferenceServiceClient fileRefs
|
||||||
) : ControllerBase
|
) : ControllerBase
|
||||||
{
|
{
|
||||||
private async Task<IActionResult> _CheckStickerPackPermissions(
|
private async Task<IActionResult> _CheckStickerPackPermissions(
|
||||||
@@ -114,6 +115,7 @@ public class StickerController(
|
|||||||
|
|
||||||
public class StickerPackRequest
|
public class StickerPackRequest
|
||||||
{
|
{
|
||||||
|
public string? IconId { get; set; }
|
||||||
[MaxLength(1024)] public string? Name { get; set; }
|
[MaxLength(1024)] public string? Name { get; set; }
|
||||||
[MaxLength(4096)] public string? Description { get; set; }
|
[MaxLength(4096)] public string? Description { get; set; }
|
||||||
[MaxLength(128)] public string? Prefix { get; set; }
|
[MaxLength(128)] public string? Prefix { get; set; }
|
||||||
@@ -147,8 +149,28 @@ public class StickerController(
|
|||||||
PublisherId = publisher.Id
|
PublisherId = publisher.Id
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (request.IconId is not null)
|
||||||
|
{
|
||||||
|
var file = await files.GetFileAsync(new GetFileRequest { Id = request.IconId });
|
||||||
|
if (file is null)
|
||||||
|
return BadRequest("Icon not found.");
|
||||||
|
|
||||||
|
pack.Icon = SnCloudFileReferenceObject.FromProtoValue(file);
|
||||||
|
}
|
||||||
|
|
||||||
db.StickerPacks.Add(pack);
|
db.StickerPacks.Add(pack);
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
|
if (pack.Icon is not null)
|
||||||
|
{
|
||||||
|
await fileRefs.CreateReferenceAsync(new CreateReferenceRequest
|
||||||
|
{
|
||||||
|
FileId = pack.Icon.Id,
|
||||||
|
Usage = StickerService.StickerPackUsageIdentifier,
|
||||||
|
ResourceId = pack.ResourceIdentifier
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return Ok(pack);
|
return Ok(pack);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,6 +201,32 @@ public class StickerController(
|
|||||||
if (request.Prefix is not null)
|
if (request.Prefix is not null)
|
||||||
pack.Prefix = request.Prefix;
|
pack.Prefix = request.Prefix;
|
||||||
|
|
||||||
|
if (request.IconId is not null)
|
||||||
|
{
|
||||||
|
var file = await files.GetFileAsync(new GetFileRequest { Id = request.IconId });
|
||||||
|
if (file is null)
|
||||||
|
return BadRequest("Icon not found.");
|
||||||
|
|
||||||
|
if (file.Id != pack.Icon?.Id)
|
||||||
|
{
|
||||||
|
await fileRefs.DeleteResourceReferencesAsync(new DeleteResourceReferencesRequest
|
||||||
|
{ ResourceId = pack.ResourceIdentifier, Usage = StickerService.StickerPackUsageIdentifier });
|
||||||
|
|
||||||
|
pack.Icon = SnCloudFileReferenceObject.FromProtoValue(file);
|
||||||
|
await fileRefs.CreateReferenceAsync(new CreateReferenceRequest
|
||||||
|
{
|
||||||
|
FileId = pack.Icon.Id,
|
||||||
|
Usage = StickerService.StickerPackUsageIdentifier,
|
||||||
|
ResourceId = pack.ResourceIdentifier
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Still update the column in case user want to sync the changes of the file meta
|
||||||
|
pack.Icon = SnCloudFileReferenceObject.FromProtoValue(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
db.StickerPacks.Update(pack);
|
db.StickerPacks.Update(pack);
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
return Ok(pack);
|
return Ok(pack);
|
||||||
@@ -239,7 +287,11 @@ public class StickerController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("search")]
|
[HttpGet("search")]
|
||||||
public async Task<ActionResult<List<SnSticker>>> SearchSticker([FromQuery] string query, [FromQuery] int take = 10, [FromQuery] int offset = 0)
|
public async Task<ActionResult<List<SnSticker>>> SearchSticker(
|
||||||
|
[FromQuery] string query,
|
||||||
|
[FromQuery] int take = 10,
|
||||||
|
[FromQuery] int offset = 0
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var queryable = db.Stickers
|
var queryable = db.Stickers
|
||||||
.Include(s => s.Pack)
|
.Include(s => s.Pack)
|
||||||
@@ -300,7 +352,6 @@ public class StickerController(
|
|||||||
var file = await files.GetFileAsync(new GetFileRequest { Id = request.ImageId });
|
var file = await files.GetFileAsync(new GetFileRequest { Id = request.ImageId });
|
||||||
if (file is null)
|
if (file is null)
|
||||||
return BadRequest("Image not found");
|
return BadRequest("Image not found");
|
||||||
sticker.ImageId = request.ImageId;
|
|
||||||
sticker.Image = SnCloudFileReferenceObject.FromProtoValue(file);
|
sticker.Image = SnCloudFileReferenceObject.FromProtoValue(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,7 +418,6 @@ public class StickerController(
|
|||||||
var sticker = new SnSticker
|
var sticker = new SnSticker
|
||||||
{
|
{
|
||||||
Slug = request.Slug,
|
Slug = request.Slug,
|
||||||
ImageId = file.Id,
|
|
||||||
Image = SnCloudFileReferenceObject.FromProtoValue(file),
|
Image = SnCloudFileReferenceObject.FromProtoValue(file),
|
||||||
Pack = pack
|
Pack = pack
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ public class StickerService(
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
public const string StickerFileUsageIdentifier = "sticker";
|
public const string StickerFileUsageIdentifier = "sticker";
|
||||||
|
public const string StickerPackUsageIdentifier = "sticker.pack";
|
||||||
|
|
||||||
private static readonly TimeSpan CacheDuration = TimeSpan.FromMinutes(15);
|
private static readonly TimeSpan CacheDuration = TimeSpan.FromMinutes(15);
|
||||||
|
|
||||||
@@ -36,7 +37,8 @@ public class StickerService(
|
|||||||
{
|
{
|
||||||
if (newImage is not null)
|
if (newImage is not null)
|
||||||
{
|
{
|
||||||
await fileRefs.DeleteResourceReferencesAsync(new DeleteResourceReferencesRequest { ResourceId = sticker.ResourceIdentifier });
|
await fileRefs.DeleteResourceReferencesAsync(new DeleteResourceReferencesRequest
|
||||||
|
{ ResourceId = sticker.ResourceIdentifier });
|
||||||
|
|
||||||
sticker.Image = newImage;
|
sticker.Image = newImage;
|
||||||
|
|
||||||
@@ -63,7 +65,8 @@ public class StickerService(
|
|||||||
var stickerResourceId = $"sticker:{sticker.Id}";
|
var stickerResourceId = $"sticker:{sticker.Id}";
|
||||||
|
|
||||||
// Delete all file references for this sticker
|
// Delete all file references for this sticker
|
||||||
await fileRefs.DeleteResourceReferencesAsync(new DeleteResourceReferencesRequest { ResourceId = stickerResourceId });
|
await fileRefs.DeleteResourceReferencesAsync(new DeleteResourceReferencesRequest
|
||||||
|
{ ResourceId = stickerResourceId });
|
||||||
|
|
||||||
db.Stickers.Remove(sticker);
|
db.Stickers.Remove(sticker);
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
@@ -82,11 +85,12 @@ public class StickerService(
|
|||||||
|
|
||||||
// Delete all file references for each sticker in the pack
|
// Delete all file references for each sticker in the pack
|
||||||
foreach (var stickerResourceId in stickers.Select(sticker => $"sticker:{sticker.Id}"))
|
foreach (var stickerResourceId in stickers.Select(sticker => $"sticker:{sticker.Id}"))
|
||||||
await fileRefs.DeleteResourceReferencesAsync(new DeleteResourceReferencesRequest { ResourceId = stickerResourceId });
|
await fileRefs.DeleteResourceReferencesAsync(new DeleteResourceReferencesRequest
|
||||||
|
{ ResourceId = stickerResourceId });
|
||||||
|
|
||||||
// Delete any references for the pack itself
|
// Delete any references for the pack itself
|
||||||
var packResourceId = $"stickerpack:{pack.Id}";
|
await fileRefs.DeleteResourceReferencesAsync(new DeleteResourceReferencesRequest
|
||||||
await fileRefs.DeleteResourceReferencesAsync(new DeleteResourceReferencesRequest { ResourceId = packResourceId });
|
{ ResourceId = pack.ResourceIdentifier });
|
||||||
|
|
||||||
db.Stickers.RemoveRange(stickers);
|
db.Stickers.RemoveRange(stickers);
|
||||||
db.StickerPacks.Remove(pack);
|
db.StickerPacks.Remove(pack);
|
||||||
@@ -119,7 +123,8 @@ public class StickerService(
|
|||||||
{
|
{
|
||||||
var packPart = identifierParts[0];
|
var packPart = identifierParts[0];
|
||||||
var stickerPart = identifierParts[1];
|
var stickerPart = identifierParts[1];
|
||||||
query = query.Where(e => EF.Functions.ILike(e.Pack.Prefix, packPart) && EF.Functions.ILike(e.Slug, stickerPart));
|
query = query.Where(e =>
|
||||||
|
EF.Functions.ILike(e.Pack.Prefix, packPart) && EF.Functions.ILike(e.Slug, stickerPart));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user