about summary refs log tree commit diff
path: root/Tests/LibMatrix.HomeserverEmulator/Controllers/Media
diff options
context:
space:
mode:
Diffstat (limited to 'Tests/LibMatrix.HomeserverEmulator/Controllers/Media')
-rw-r--r--Tests/LibMatrix.HomeserverEmulator/Controllers/Media/MediaController.cs99
1 files changed, 93 insertions, 6 deletions
diff --git a/Tests/LibMatrix.HomeserverEmulator/Controllers/Media/MediaController.cs b/Tests/LibMatrix.HomeserverEmulator/Controllers/Media/MediaController.cs
index dba36d7..4820a65 100644
--- a/Tests/LibMatrix.HomeserverEmulator/Controllers/Media/MediaController.cs
+++ b/Tests/LibMatrix.HomeserverEmulator/Controllers/Media/MediaController.cs
@@ -1,14 +1,26 @@
+using System.Text.Json.Nodes;
+using System.Text.RegularExpressions;
+using ArcaneLibs.Extensions;
 using LibMatrix.HomeserverEmulator.Services;
+using LibMatrix.Services;
+using Microsoft.AspNetCore.Html;
 using Microsoft.AspNetCore.Mvc;
 
 namespace LibMatrix.HomeserverEmulator.Controllers.Media;
 
 [ApiController]
 [Route("/_matrix/media/{version}/")]
-public class MediaController(ILogger<MediaController> logger, TokenService tokenService, UserStore userStore, RoomStore roomStore) : ControllerBase {
+public class MediaController(
+    ILogger<MediaController> logger,
+    TokenService tokenService,
+    UserStore userStore,
+    HSEConfiguration cfg,
+    HomeserverResolverService hsResolver,
+    MediaStore mediaStore)
+    : ControllerBase {
     [HttpPost("upload")]
     public async Task<object> UploadMedia([FromHeader(Name = "Content-Type")] string ContentType, [FromQuery] string filename, [FromBody] Stream file) {
-        var token = tokenService.GetAccessToken(HttpContext);
+        var token = tokenService.GetAccessTokenOrNull(HttpContext);
         if (token == null)
             throw new MatrixException() {
                 ErrorCode = "M_MISSING_TOKEN",
@@ -21,14 +33,89 @@ public class MediaController(ILogger<MediaController> logger, TokenService token
                 ErrorCode = "M_UNKNOWN_TOKEN",
                 Error = "No such user"
             };
-        
-        
-        
+
         var mediaId = Guid.NewGuid().ToString();
         var media = new {
             content_uri = $"mxc://{tokenService.GenerateServerName(HttpContext)}/{mediaId}"
         };
         return media;
-        
+    }
+
+    private Dictionary<string, SemaphoreSlim> downloadLocks = new();
+
+    [HttpGet("download/{serverName}/{mediaId}")]
+    public async Task DownloadMedia(string serverName, string mediaId) {
+        while (true)
+            try {
+                if (cfg.StoreData) {
+                    SemaphoreSlim ss;
+                    if (!downloadLocks.ContainsKey(serverName + mediaId))
+                        downloadLocks[serverName + mediaId] = new SemaphoreSlim(1);
+                    ss = downloadLocks[serverName + mediaId];
+                    await ss.WaitAsync();
+                    var serverMediaPath = Path.Combine(cfg.DataStoragePath, "media", serverName);
+                    Directory.CreateDirectory(serverMediaPath);
+                    var mediaPath = Path.Combine(serverMediaPath, mediaId);
+                    if (System.IO.File.Exists(mediaPath)) {
+                        ss.Release();
+                        await using var stream = new FileStream(mediaPath, FileMode.Open);
+                        await stream.CopyToAsync(Response.Body);
+                        return;
+                    }
+                    else {
+                        var mediaUrl = await hsResolver.ResolveMediaUri(serverName, $"mxc://{serverName}/{mediaId}");
+                        if (mediaUrl is null)
+                            throw new MatrixException() {
+                                ErrorCode = "M_NOT_FOUND",
+                                Error = "Media not found"
+                            };
+                        await using var stream = System.IO.File.OpenWrite(mediaPath);
+                        using var response = await new HttpClient().GetAsync(mediaUrl);
+                        await response.Content.CopyToAsync(stream);
+                        await stream.FlushAsync();
+                        ss.Release();
+                        await DownloadMedia(serverName, mediaId);
+                        return;
+                    }
+                }
+                else {
+                    var mediaUrl = await hsResolver.ResolveMediaUri(serverName, $"mxc://{serverName}/{mediaId}");
+                    if (mediaUrl is null)
+                        throw new MatrixException() {
+                            ErrorCode = "M_NOT_FOUND",
+                            Error = "Media not found"
+                        };
+                    using var response = await new HttpClient().GetAsync(mediaUrl);
+                    await response.Content.CopyToAsync(Response.Body);
+                    return;
+                }
+
+                return;
+            }
+            catch (IOException) {
+                //ignored
+            }
+    }
+
+    [HttpGet("thumbnail/{serverName}/{mediaId}")]
+    public async Task DownloadThumbnail(string serverName, string mediaId) {
+        await DownloadMedia(serverName, mediaId);
+    }
+
+    [HttpGet("preview_url")]
+    public async Task<JsonObject> GetPreviewUrl([FromQuery] string url) {
+        JsonObject data = new();
+
+        using var hc = new HttpClient();
+        using var response = await hc.GetAsync(url);
+        var doc = await response.Content.ReadAsStringAsync();
+        var match = Regex.Match(doc, "<meta property=\"(.*?)\" content=\"(.*?)\"");
+
+        while (match.Success) {
+            data[match.Groups[1].Value] = match.Groups[2].Value;
+            match = match.NextMatch();
+        }
+
+        return data;
     }
 }
\ No newline at end of file