[backend/masto-client] Add missing media endpoints, handle media_attributes on status update (ISH-155)

This commit is contained in:
Laura Hausmann 2024-03-14 11:49:48 +01:00
parent 80da86897f
commit a2075d4c63
No known key found for this signature in database
GPG key ID: D044E84C5BE01605
5 changed files with 73 additions and 7 deletions

View file

@ -2,11 +2,15 @@ using System.Net.Mime;
using Iceshrimp.Backend.Controllers.Mastodon.Attributes; using Iceshrimp.Backend.Controllers.Mastodon.Attributes;
using Iceshrimp.Backend.Controllers.Mastodon.Schemas; using Iceshrimp.Backend.Controllers.Mastodon.Schemas;
using Iceshrimp.Backend.Controllers.Mastodon.Schemas.Entities; using Iceshrimp.Backend.Controllers.Mastodon.Schemas.Entities;
using Iceshrimp.Backend.Core.Database;
using Iceshrimp.Backend.Core.Database.Tables;
using Iceshrimp.Backend.Core.Extensions;
using Iceshrimp.Backend.Core.Middleware; using Iceshrimp.Backend.Core.Middleware;
using Iceshrimp.Backend.Core.Services; using Iceshrimp.Backend.Core.Services;
using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.RateLimiting; using Microsoft.AspNetCore.RateLimiting;
using Microsoft.EntityFrameworkCore;
namespace Iceshrimp.Backend.Controllers.Mastodon; namespace Iceshrimp.Backend.Controllers.Mastodon;
@ -17,11 +21,10 @@ namespace Iceshrimp.Backend.Controllers.Mastodon;
[EnableRateLimiting("sliding")] [EnableRateLimiting("sliding")]
[Produces(MediaTypeNames.Application.Json)] [Produces(MediaTypeNames.Application.Json)]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(AttachmentEntity))] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(AttachmentEntity))]
public class MediaController(DriveService driveSvc) : ControllerBase public class MediaController(DriveService driveSvc, DatabaseContext db) : ControllerBase
{ {
[HttpPost("/api/v1/media")] [HttpPost("/api/v1/media")]
[HttpPost("/api/v2/media")] [HttpPost("/api/v2/media")]
[ProducesResponseType(StatusCodes.Status404NotFound, Type = typeof(MastodonErrorResponse))]
public async Task<IActionResult> UploadAttachment(MediaSchemas.UploadMediaRequest request) public async Task<IActionResult> UploadAttachment(MediaSchemas.UploadMediaRequest request)
{ {
var user = HttpContext.GetUserOrFail(); var user = HttpContext.GetUserOrFail();
@ -33,7 +36,40 @@ public class MediaController(DriveService driveSvc) : ControllerBase
MimeType = request.File.ContentType MimeType = request.File.ContentType
}; };
var file = await driveSvc.StoreFile(request.File.OpenReadStream(), user, rq); var file = await driveSvc.StoreFile(request.File.OpenReadStream(), user, rq);
var res = new AttachmentEntity var res = RenderAttachment(file);
return Ok(res);
}
[HttpPut("/api/v1/media/{id}")]
[ProducesResponseType(StatusCodes.Status404NotFound, Type = typeof(MastodonErrorResponse))]
public async Task<IActionResult> UpdateAttachment(string id, [FromHybrid] MediaSchemas.UpdateMediaRequest request)
{
var user = HttpContext.GetUserOrFail();
var file = await db.DriveFiles.FirstOrDefaultAsync(p => p.Id == id && p.User == user) ??
throw GracefulException.RecordNotFound();
file.Comment = request.Description;
await db.SaveChangesAsync();
var res = RenderAttachment(file);
return Ok(res);
}
[HttpGet("/api/v1/media/{id}")]
[ProducesResponseType(StatusCodes.Status404NotFound, Type = typeof(MastodonErrorResponse))]
public async Task<IActionResult> GetAttachment(string id)
{
var user = HttpContext.GetUserOrFail();
var file = await db.DriveFiles.FirstOrDefaultAsync(p => p.Id == id && p.User == user) ??
throw GracefulException.RecordNotFound();
var res = RenderAttachment(file);
return Ok(res);
}
private static AttachmentEntity RenderAttachment(DriveFile file)
{
return new AttachmentEntity
{ {
Id = file.Id, Id = file.Id,
Type = AttachmentEntity.GetType(file.Type), Type = AttachmentEntity.GetType(file.Type),
@ -44,7 +80,5 @@ public class MediaController(DriveService driveSvc) : ControllerBase
RemoteUrl = file.Uri RemoteUrl = file.Uri
//Metadata = TODO //Metadata = TODO
}; };
return Ok(res);
} }
} }

View file

@ -1,4 +1,6 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using J = System.Text.Json.Serialization.JsonPropertyNameAttribute;
using B = Microsoft.AspNetCore.Mvc.BindPropertyAttribute;
namespace Iceshrimp.Backend.Controllers.Mastodon.Schemas; namespace Iceshrimp.Backend.Controllers.Mastodon.Schemas;
@ -11,4 +13,13 @@ public abstract class MediaSchemas
//TODO: add thumbnail & focus properties //TODO: add thumbnail & focus properties
} }
public class UpdateMediaRequest
{
[J("description")]
[B(Name = "description")]
public string? Description { get; set; }
//TODO: add thumbnail & focus properties
}
} }

View file

@ -83,8 +83,15 @@ public abstract class StatusSchemas
[J("media_ids")] [J("media_ids")]
public List<string>? MediaIds { get; set; } public List<string>? MediaIds { get; set; }
//TODO: media_attributes [B(Name = "media_attributes")]
[J("media_attributes")]
public List<MediaAttributesEntry>? MediaAttributes { get; set; }
[B(Name = "poll")] [J("poll")] public PostStatusRequest.PollData? Poll { get; set; } [B(Name = "poll")] [J("poll")] public PostStatusRequest.PollData? Poll { get; set; }
} }
public class MediaAttributesEntry : MediaSchemas.UpdateMediaRequest
{
[JR] [J("id")] [B(Name = "id")] public required string Id { get; set; }
}
} }

View file

@ -423,6 +423,18 @@ public class StatusController(
? await db.DriveFiles.Where(p => request.MediaIds.Contains(p.Id)).ToListAsync() ? await db.DriveFiles.Where(p => request.MediaIds.Contains(p.Id)).ToListAsync()
: []; : [];
if (request.MediaAttributes != null)
{
foreach (var attr in request.MediaAttributes)
{
var file = attachments.FirstOrDefault(p => p.Id == attr.Id);
if (file != null)
file.Comment = attr.Description;
}
await db.SaveChangesAsync();
}
note = await noteSvc.UpdateNoteAsync(note, request.Text, request.Cw, attachments, poll); note = await noteSvc.UpdateNoteAsync(note, request.Text, request.Cw, attachments, poll);
var res = await noteRenderer.RenderAsync(note, user); var res = await noteRenderer.RenderAsync(note, user);

View file

@ -246,6 +246,8 @@ public class NoteService(
await ResolveNoteMentionsAsync(text); await ResolveNoteMentionsAsync(text);
if (text != null) if (text != null)
text = mentionsResolver.ResolveMentions(text, null, mentions, splitDomainMapping); text = mentionsResolver.ResolveMentions(text, null, mentions, splitDomainMapping);
if (cw != null && string.IsNullOrWhiteSpace(cw))
cw = null;
mentionedLocalUserIds = mentionedLocalUserIds.Except(previousMentionedLocalUserIds).ToList(); mentionedLocalUserIds = mentionedLocalUserIds.Except(previousMentionedLocalUserIds).ToList();
note.Text = text?.Trim(); note.Text = text?.Trim();