mirror of
https://github.com/JogmansonReal/Radicade.git
synced 2026-10-25 23:18:56 -07:00
581 lines
19 KiB
C#
581 lines
19 KiB
C#
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using RadicadeServer.DB;
|
|
using RadicadeServer.Extensions;
|
|
using RadicadeServer.RecNet.CDN;
|
|
using RadicadeServer.RecNet.Enums;
|
|
using RadicadeServer.RecNet.Images;
|
|
using RadicadeServer.RecNet.Responses;
|
|
using RadicadeServer.Radicade.Discord.Templates;
|
|
|
|
namespace RadicadeServer.API
|
|
{
|
|
[Route("api/images")]
|
|
public class ImagesAPI : Controller
|
|
{
|
|
RecDBContext db;
|
|
public ImagesAPI(RecDBContext context)
|
|
{
|
|
this.db = context;
|
|
}
|
|
|
|
|
|
private static object ToSavedImage(ImageDB image, int cheerCount) => new
|
|
{
|
|
Id = image.Id,
|
|
SavedImageId = image.Id,
|
|
Type = (int)image.ImageType,
|
|
SavedImageType = (int)image.ImageType,
|
|
Accessibility = (int)image.Accessibility,
|
|
AccessibilityLocked = false,
|
|
ImageName = image.Name,
|
|
Description = (string?)null,
|
|
PlayerId = image.OwnerId,
|
|
TaggedPlayerIds = ParseTaggedPlayerIds(image.PlayerIds),
|
|
RoomId = image.RoomId,
|
|
PlayerEventId = image.EventId,
|
|
CreatedAt = image.CreatedAt,
|
|
CheerCount = cheerCount,
|
|
CommentCount = 0
|
|
};
|
|
|
|
private static object ToImagesPlayer(ImageDB image, int cheerCount) => new
|
|
{
|
|
SavedImageId = image.Id,
|
|
Id = image.Id,
|
|
SavedImageType = (int)image.ImageType,
|
|
Type = (int)image.ImageType,
|
|
Accessibility = (int)image.Accessibility,
|
|
AccessibilityLocked = false,
|
|
CheerCount = cheerCount,
|
|
CommentCount = 0,
|
|
CreatedAt = image.CreatedAt,
|
|
Description = (string?)null,
|
|
ImageName = image.Name,
|
|
PlayerEventId = image.EventId,
|
|
PlayerId = image.OwnerId,
|
|
RoomId = image.RoomId
|
|
};
|
|
|
|
private static List<long> ParseTaggedPlayerIds(string json)
|
|
{
|
|
try
|
|
{
|
|
return string.IsNullOrWhiteSpace(json)
|
|
? new List<long>()
|
|
: (json.FromJson<List<long>>() ?? new List<long>());
|
|
}
|
|
catch
|
|
{
|
|
return new List<long>();
|
|
}
|
|
}
|
|
|
|
private async Task<Dictionary<long, int>> CheerCountsAsync(IEnumerable<long> imageIds)
|
|
{
|
|
var ids = imageIds.Distinct().ToList();
|
|
if (ids.Count == 0)
|
|
return new Dictionary<long, int>();
|
|
|
|
return await db.ImageInteractions.AsNoTracking()
|
|
.Where(c => c.IsCheered && ids.Contains(c.SavedImageId))
|
|
.GroupBy(c => c.SavedImageId)
|
|
.Select(g => new { g.Key, Count = g.Count() })
|
|
.ToDictionaryAsync(g => g.Key, g => g.Count);
|
|
}
|
|
|
|
private static string[] TagMatchPatterns(long playerId) => new[]
|
|
{
|
|
$"[{playerId},", $",{playerId},", $",{playerId}]", $"[{playerId}]"
|
|
};
|
|
|
|
|
|
[HttpGet("v5/player/{id:long}")]
|
|
public async Task<List<object>> GetImagesFromPlayer(long id, [FromQuery] int sort = 0, [FromQuery] int skip = 0, [FromQuery] int take = 100)
|
|
{
|
|
var images = await db.Images.AsNoTracking()
|
|
.Where(image => image.OwnerId == id && image.Accessibility == SavedImageAccessibility.Public)
|
|
.ToListAsync();
|
|
|
|
var cheers = await CheerCountsAsync(images.Select(image => image.Id));
|
|
var ordered = OrderImages(images, sort, cheers)
|
|
.Skip(skip).Take(take)
|
|
.ToList();
|
|
|
|
return ordered.Select(image => ToImagesPlayer(image, cheers.GetValueOrDefault(image.Id))).ToList();
|
|
}
|
|
|
|
[HttpGet("v4/player/{id:long}")]
|
|
public Task<List<object>> GetImagesFromPlayerV4(long id, [FromQuery] int skip = 0, [FromQuery] int take = 100)
|
|
=> GetImagesFromPlayer(id, 0, skip, take);
|
|
|
|
[HttpGet("v4/room/{id}")]
|
|
public async Task<List<object>> GetImagesFromRoom(long? id, [FromQuery] int sort = 0, [FromQuery] int filter = 0, [FromQuery] int skip = 0, [FromQuery] int take = 100)
|
|
{
|
|
var result = new List<object>();
|
|
if (id == null)
|
|
return result;
|
|
|
|
var images = await db.Images.AsNoTracking()
|
|
.Where(x => x.RoomId == id && x.Accessibility == SavedImageAccessibility.Public)
|
|
.ToListAsync();
|
|
|
|
if (filter > 0)
|
|
images = images.Where(x => (int)x.ImageType == filter).ToList();
|
|
|
|
var cheers = await CheerCountsAsync(images.Select(x => x.Id));
|
|
var ordered = OrderImages(images, sort, cheers)
|
|
.Skip(skip).Take(take)
|
|
.ToList();
|
|
|
|
return ordered.Select(image => ToSavedImage(image, cheers.GetValueOrDefault(image.Id))).ToList();
|
|
}
|
|
|
|
[HttpGet("v1/playerevent/{eventId}")]
|
|
public async Task<List<object>> GetImagesFromEvent(long eventId, [FromQuery] int skip = 0, [FromQuery] int take = 100)
|
|
{
|
|
var images = await db.Images.AsNoTracking()
|
|
.Where(x => x.EventId == eventId && x.Accessibility == SavedImageAccessibility.Public)
|
|
.ToListAsync();
|
|
|
|
var cheers = await CheerCountsAsync(images.Select(x => x.Id));
|
|
var ordered = OrderImages(images, 0, cheers)
|
|
.Skip(skip).Take(take)
|
|
.ToList();
|
|
|
|
return ordered.Select(image => ToSavedImage(image, cheers.GetValueOrDefault(image.Id))).ToList();
|
|
}
|
|
|
|
private static IEnumerable<ImageDB> OrderImages(IEnumerable<ImageDB> images, int sort, Dictionary<long, int> cheers)
|
|
{
|
|
return sort == 1
|
|
? images.OrderByDescending(x => cheers.GetValueOrDefault(x.Id))
|
|
.ThenByDescending(x => x.CreatedAt).ThenByDescending(x => x.Id)
|
|
: images.OrderByDescending(x => x.CreatedAt).ThenByDescending(x => x.Id);
|
|
}
|
|
|
|
|
|
[HttpGet("v3/feed/player/{id:long}")]
|
|
public async Task<List<object>> GetPlayerFeed(long id, [FromQuery] int skip = 0, [FromQuery] int take = 100)
|
|
{
|
|
var patterns = TagMatchPatterns(id);
|
|
var images = await db.Images.AsNoTracking()
|
|
.Where(x => x.Accessibility == SavedImageAccessibility.Public &&
|
|
(x.OwnerId == id ||
|
|
x.PlayerIds.Contains(patterns[0]) ||
|
|
x.PlayerIds.Contains(patterns[1]) ||
|
|
x.PlayerIds.Contains(patterns[2]) ||
|
|
x.PlayerIds.Contains(patterns[3])))
|
|
.ToListAsync();
|
|
|
|
var cheers = await CheerCountsAsync(images.Select(x => x.Id));
|
|
var ordered = OrderImages(images, 0, cheers)
|
|
.Skip(skip).Take(take)
|
|
.ToList();
|
|
|
|
return ordered.Select(image => ToImagesPlayer(image, cheers.GetValueOrDefault(image.Id))).ToList();
|
|
}
|
|
|
|
[HttpGet("v3/feed/global")]
|
|
public async Task<object> GetGlobalFeed([FromQuery] int skip = 0, [FromQuery] int take = 100)
|
|
{
|
|
var images = await db.Images.AsNoTracking()
|
|
.Where(x => x.Accessibility == SavedImageAccessibility.Public &&
|
|
x.ImageType == SavedImageType.ShareCamera)
|
|
.OrderByDescending(x => x.CreatedAt).ThenByDescending(x => x.Id)
|
|
.Skip(skip).Take(Math.Clamp(take, 1, 100))
|
|
.ToListAsync();
|
|
|
|
var ownerIds = images.Select(x => x.OwnerId).Distinct().ToList();
|
|
var roomIds = images.Where(x => x.RoomId != null).Select(x => x.RoomId!.Value).Distinct().ToList();
|
|
|
|
var usernames = await db.Profiles.AsNoTracking()
|
|
.Where(p => ownerIds.Contains(p.accountId))
|
|
.ToDictionaryAsync(p => p.accountId, p => p.username);
|
|
var roomNames = await db.Rooms.AsNoTracking()
|
|
.Where(r => roomIds.Contains(r.RoomId))
|
|
.ToDictionaryAsync(r => r.RoomId, r => r.Name);
|
|
|
|
var entries = images.Select(image => new
|
|
{
|
|
SavedImageId = image.Id,
|
|
ImageName = image.Name,
|
|
Username = usernames.TryGetValue(image.OwnerId, out var username) ? username : $"Player{image.OwnerId}",
|
|
RoomName = image.RoomId != null && roomNames.TryGetValue(image.RoomId.Value, out var roomName) ? roomName : (string?)null,
|
|
RoomId = image.RoomId,
|
|
SavedImageType = (int)image.ImageType,
|
|
PlayerEventId = image.EventId,
|
|
Accessibility = (int)image.Accessibility,
|
|
PlayerIds = ParseTaggedPlayerIds(image.PlayerIds)
|
|
}).ToList();
|
|
|
|
return new { Images = entries, ValidTill = DateTime.UtcNow.AddMinutes(2) };
|
|
}
|
|
|
|
[HttpGet("v3/bulk")]
|
|
public async Task<List<object>> GetBulkImages([FromQuery] string ids)
|
|
{
|
|
var result = new List<object>();
|
|
if (string.IsNullOrWhiteSpace(ids))
|
|
return result;
|
|
|
|
var parsed = ids
|
|
.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
|
|
.Select(part => long.TryParse(part, out var value) ? value : -1)
|
|
.Where(value => value > 0)
|
|
.ToList();
|
|
if (parsed.Count == 0)
|
|
return result;
|
|
|
|
var images = await db.Images.AsNoTracking()
|
|
.Where(x => parsed.Contains(x.Id) && x.Accessibility == SavedImageAccessibility.Public)
|
|
.ToListAsync();
|
|
var byId = images.ToDictionary(x => x.Id);
|
|
var cheers = await CheerCountsAsync(images.Select(x => x.Id));
|
|
|
|
foreach (var id in parsed)
|
|
{
|
|
if (byId.TryGetValue(id, out var image))
|
|
result.Add(ToSavedImage(image, cheers.GetValueOrDefault(image.Id)));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
[HttpGet("v4/{photoId:long}")]
|
|
public async Task<IActionResult> GetImageById(long photoId)
|
|
{
|
|
var image = await db.Images.AsNoTracking().FirstOrDefaultAsync(x => x.Id == photoId);
|
|
if (image == null)
|
|
return NotFound();
|
|
|
|
|
|
|
|
|
|
|
|
if (image.Accessibility == SavedImageAccessibility.Private)
|
|
return NotFound();
|
|
return Ok(ToSavedImage(image, await db.ImageInteractions.AsNoTracking()
|
|
.CountAsync(c => c.SavedImageId == image.Id && c.IsCheered)));
|
|
}
|
|
|
|
[HttpGet("v5/bulk")]
|
|
public async Task<List<object>> GetBulkImageMetadata([FromQuery] string[]? ids)
|
|
{
|
|
var result = new List<object>();
|
|
var parsed = (ids ?? Array.Empty<string>())
|
|
.SelectMany(raw => (raw ?? "").Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
|
|
.Select(part => long.TryParse(part, out var value) ? value : -1)
|
|
.Where(value => value > 0)
|
|
.Distinct()
|
|
.ToList();
|
|
if (parsed.Count == 0)
|
|
return result;
|
|
|
|
var images = await db.Images.AsNoTracking()
|
|
.Where(x => parsed.Contains(x.Id) && x.Accessibility == SavedImageAccessibility.Public)
|
|
.ToListAsync();
|
|
var byId = images.ToDictionary(x => x.Id);
|
|
var cheers = await CheerCountsAsync(images.Select(x => x.Id));
|
|
|
|
foreach (var id in parsed)
|
|
{
|
|
if (byId.TryGetValue(id, out var image))
|
|
result.Add(ToBulkSavedImage(image, cheers.GetValueOrDefault(image.Id)));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private static object ToBulkSavedImage(ImageDB image, int cheerCount) => new
|
|
{
|
|
Id = image.Id,
|
|
Type = (int)image.ImageType,
|
|
Accessibility = (int)image.Accessibility,
|
|
AccessibilityLocked = false,
|
|
ImageName = image.Name,
|
|
Description = (string?)null,
|
|
PlayerId = image.OwnerId,
|
|
TaggedPlayerIds = ParseTaggedPlayerIds(image.PlayerIds),
|
|
RoomId = image.RoomId,
|
|
PlayerEventId = image.EventId,
|
|
CreatedAt = image.CreatedAt,
|
|
CheerCount = cheerCount,
|
|
CommentCount = 0,
|
|
SavedImageId = image.Id,
|
|
SavedImageType = (int)image.ImageType,
|
|
ClubId = 0
|
|
};
|
|
|
|
[HttpGet("v6")]
|
|
public async Task<IActionResult> GetImageByName([FromQuery] string name)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(name))
|
|
return BadRequest(new { error = "name is required" });
|
|
|
|
var image = await db.Images.AsNoTracking().FirstOrDefaultAsync(x => x.Name == name);
|
|
if (image == null)
|
|
return NotFound();
|
|
|
|
|
|
|
|
if (image.Accessibility == SavedImageAccessibility.Private)
|
|
return NotFound();
|
|
|
|
var viewerId = User.GetUserId() ?? Request.Headers.Authorization.ToString().GetUserId();
|
|
if (viewerId != null)
|
|
RecentImageReferences.Remember(viewerId.Value, image.Id);
|
|
|
|
return Ok(new
|
|
{
|
|
SavedImageId = image.Id,
|
|
ImageName = image.Name,
|
|
PlayerId = image.OwnerId,
|
|
RoomId = image.RoomId ?? 0,
|
|
PlayerEventId = image.EventId ?? 0,
|
|
ClubId = 0,
|
|
Description = "",
|
|
Accessibility = (int)image.Accessibility,
|
|
AccessibilityLocked = false,
|
|
SavedImageType = (int)image.ImageType,
|
|
CreatedAt = image.CreatedAt,
|
|
CheerCount = await db.ImageInteractions.AsNoTracking()
|
|
.CountAsync(c => c.SavedImageId == image.Id && c.IsCheered),
|
|
CommentCount = 0
|
|
});
|
|
}
|
|
|
|
|
|
[HttpPost("v1/cheer"), Authorize]
|
|
public async Task<Success> CheerImage([FromBody] ImageCheerRequest req)
|
|
{
|
|
var userId = User.GetUserId();
|
|
if (userId == null)
|
|
return new Success(false, "Not signed in", null);
|
|
|
|
var existingInteraction = await db.ImageInteractions.FirstOrDefaultAsync(x =>
|
|
x.PlayerId == userId && x.SavedImageId == req.SavedImageId);
|
|
if (existingInteraction != null)
|
|
existingInteraction.IsCheered = req.Cheer;
|
|
else
|
|
await db.ImageInteractions.AddAsync(
|
|
new CheeredImage { IsCheered = req.Cheer, PlayerId = (long)userId, SavedImageId = req.SavedImageId }
|
|
);
|
|
|
|
await db.SaveChangesAsync();
|
|
|
|
return new Success(true, null, null);
|
|
}
|
|
|
|
[HttpGet("v1/{imageId:long}/cheers")]
|
|
public async Task<List<long>> GetImageCheers(long imageId)
|
|
{
|
|
return await db.ImageInteractions.AsNoTracking()
|
|
.Where(x => x.SavedImageId == imageId && x.IsCheered)
|
|
.Select(x => x.PlayerId)
|
|
.ToListAsync();
|
|
}
|
|
|
|
[HttpGet("v2/named")]
|
|
public List<NamedImage> GetNamedImages()
|
|
{
|
|
var config = db.ServerConfig.FirstOrDefault(x => x.Key == "NamedImages");
|
|
return config?.Value.FromJson<List<NamedImage>>() ?? new List<NamedImage>();
|
|
}
|
|
|
|
private async Task<List<object>> CheerLookup(List<long> ids)
|
|
{
|
|
var userId = User.GetUserId();
|
|
if (userId == null)
|
|
return new List<object>();
|
|
|
|
ids ??= new List<long>();
|
|
var cheeredIds = await db.ImageInteractions.AsNoTracking()
|
|
.Where(x => x.PlayerId == userId && x.IsCheered && ids.Contains(x.SavedImageId))
|
|
.Select(x => x.SavedImageId)
|
|
.ToListAsync();
|
|
var cheeredSet = cheeredIds.ToHashSet();
|
|
|
|
return ids.Select(id => (object)new { SavedImageId = id, IsCheered = cheeredSet.Contains(id) }).ToList();
|
|
}
|
|
|
|
[HttpGet("v5/cheered/bulk"), Authorize]
|
|
public Task<List<object>> GetBulkImageCheers([FromQuery] long[] id)
|
|
=> CheerLookup((id ?? Array.Empty<long>()).ToList());
|
|
|
|
[HttpPost("v5/cheered/bulk"), Authorize]
|
|
public async Task<List<object>> PostBulkImageCheers()
|
|
{
|
|
var ids = new List<long>();
|
|
if (Request.HasFormContentType)
|
|
{
|
|
var form = await Request.ReadFormAsync();
|
|
foreach (var value in form["id"])
|
|
{
|
|
if (long.TryParse(value, out var parsed))
|
|
ids.Add(parsed);
|
|
}
|
|
}
|
|
return await CheerLookup(ids);
|
|
}
|
|
|
|
|
|
[HttpPost("v1/{imageId:long}/report"), Authorize]
|
|
public async Task<IActionResult> ReportImage(long imageId)
|
|
{
|
|
await Task.CompletedTask;
|
|
return Ok(new { success = true });
|
|
}
|
|
|
|
[HttpPost("v1/{imageId:long}/player/{playerId:long}/untag"), Authorize]
|
|
public async Task<IActionResult> UntagFromImage(long imageId, long playerId)
|
|
{
|
|
var userId = User.GetUserId();
|
|
|
|
var image = await db.Images.FirstOrDefaultAsync(x => x.Id == imageId);
|
|
if (image == null)
|
|
return NotFound();
|
|
|
|
if (userId != playerId && userId != image.OwnerId)
|
|
return StatusCode(403);
|
|
|
|
var tagged = ParseTaggedPlayerIds(image.PlayerIds);
|
|
if (!tagged.Remove(playerId))
|
|
return Ok(new { success = true });
|
|
|
|
image.PlayerIds = tagged.ToJson();
|
|
await db.SaveChangesAsync();
|
|
return Ok(new { success = true });
|
|
}
|
|
|
|
|
|
[HttpPost("v4/uploadsaved"), Authorize]
|
|
public async Task<ActionResult<ImageNameDTO?>> UploadSavedImage([FromForm] IFormFile? image, [FromForm] SavedImageMetaDTO? imgMeta)
|
|
{
|
|
if (imgMeta == null)
|
|
return BadRequest();
|
|
if (image == null || image.Length <= 0 || image.Length >= 2 * 1024 * 1024)
|
|
return StatusCode(413);
|
|
|
|
var userId = User.GetUserId();
|
|
if (userId == null)
|
|
return Unauthorized();
|
|
|
|
var presence = await db.Presences.FirstOrDefaultAsync(x => x.playerId == userId);
|
|
var roomInstance = presence != null
|
|
? await db.RoomInstances.FirstOrDefaultAsync(x => x.roomInstanceId == presence.roomInstance)
|
|
: null;
|
|
|
|
string imageName = Guid.NewGuid().ToString() + ".png";
|
|
string path = Path.Join(DBConfig.CDNImages, imageName);
|
|
|
|
using (var stream = new FileStream(path, FileMode.Create))
|
|
{
|
|
await image.CopyToAsync(stream);
|
|
}
|
|
|
|
SavedImageAccessibility accessibility = imgMeta.accessibility;
|
|
if (imgMeta.savedImageType == SavedImageType.InventionThumbnail ||
|
|
imgMeta.savedImageType == SavedImageType.OutfitThumbnail ||
|
|
imgMeta.savedImageType == SavedImageType.ProfileThumbnail ||
|
|
imgMeta.savedImageType == SavedImageType.RoomThumbnail)
|
|
{
|
|
accessibility = SavedImageAccessibility.Private;
|
|
}
|
|
|
|
var taggedPlayerIds = (imgMeta.playerIds ?? new List<long>())
|
|
.Where(id => id > 0)
|
|
.Distinct()
|
|
.ToList();
|
|
|
|
var savedImage = new ImageDB { CreatedAt = DateTime.Now, Name = imageName, OwnerId = (long)userId, Accessibility = accessibility, ImageType = imgMeta.savedImageType, RoomId = imgMeta.roomId ?? roomInstance?.roomId, EventId = imgMeta.playerEventId, PlayerIds = taggedPlayerIds.ToJson() };
|
|
await db.Images.AddAsync(savedImage);
|
|
await db.SaveChangesAsync();
|
|
|
|
RecentImageReferences.Remember((long)userId, savedImage.Id);
|
|
|
|
if (imgMeta.savedImageType == SavedImageType.ProfileThumbnail)
|
|
{
|
|
var profile = await db.Profiles.FirstOrDefaultAsync(x => x.accountId == userId);
|
|
if (profile != null)
|
|
{
|
|
profile.profileImage = imageName;
|
|
await db.SaveChangesAsync();
|
|
}
|
|
}
|
|
|
|
if (accessibility == SavedImageAccessibility.Public || imgMeta.savedImageType == SavedImageType.ShareCamera)
|
|
{
|
|
var room = await db.Rooms.AsNoTracking().FirstOrDefaultAsync(x => x.RoomId == imgMeta.roomId);
|
|
var ownerProfile = await db.Profiles.AsNoTracking().FirstOrDefaultAsync(x => x.accountId == userId);
|
|
|
|
string? roomName = null;
|
|
|
|
if (ownerProfile != null)
|
|
{
|
|
if (room != null)
|
|
{
|
|
if (room.Accessibility >= Accessibility.Public)
|
|
roomName = "^" + room.Name;
|
|
else if (room.IsDorm && roomInstance != null)
|
|
roomName = roomInstance?.name;
|
|
else
|
|
roomName = "[PRIVATE]";
|
|
}
|
|
|
|
await WebhookImageUpload.Send($"{DBConfig.NameServer.Images}/img/{imageName}", ownerProfile.username, ownerProfile.displayName, $"{DBConfig.NameServer.Images}/img/{ownerProfile.profileImage}", roomName);
|
|
}
|
|
}
|
|
|
|
return new ImageNameDTO { ImageName = imageName };
|
|
}
|
|
|
|
[HttpDelete("v1/deletesaved"), Authorize]
|
|
[HttpPost("v1/deletesaved"), Authorize]
|
|
public async Task<IActionResult> DeleteSavedImage()
|
|
{
|
|
var userId = User.GetUserId();
|
|
string? imageName = null;
|
|
|
|
if (Request.HasFormContentType)
|
|
{
|
|
var form = await Request.ReadFormAsync();
|
|
imageName = form["ImageName"].ToString();
|
|
if (string.IsNullOrWhiteSpace(imageName))
|
|
imageName = form["imageName"].ToString();
|
|
}
|
|
else
|
|
{
|
|
try
|
|
{
|
|
using var doc = await System.Text.Json.JsonDocument.ParseAsync(Request.Body);
|
|
if (doc.RootElement.ValueKind == System.Text.Json.JsonValueKind.Object &&
|
|
doc.RootElement.TryGetProperty("ImageName", out var prop) &&
|
|
prop.ValueKind == System.Text.Json.JsonValueKind.String)
|
|
imageName = prop.GetString();
|
|
}
|
|
catch (System.Text.Json.JsonException) { }
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(imageName))
|
|
return BadRequest(new { error = "ImageName is required" });
|
|
|
|
var image = await db.Images.FirstOrDefaultAsync(x => x.Name == imageName);
|
|
if (image == null)
|
|
return NotFound();
|
|
if (image.OwnerId != userId)
|
|
return StatusCode(403, new { error = "Not your image" });
|
|
|
|
var cheers = db.ImageInteractions.Where(x => x.SavedImageId == image.Id);
|
|
db.ImageInteractions.RemoveRange(cheers);
|
|
db.Images.Remove(image);
|
|
await db.SaveChangesAsync();
|
|
|
|
var fullPath = Path.Join(DBConfig.CDNImages, imageName);
|
|
if (System.IO.File.Exists(fullPath))
|
|
System.IO.File.Delete(fullPath);
|
|
|
|
return Ok(new { success = true });
|
|
}
|
|
}
|
|
}
|