diff --git a/Iceshrimp.Backend/Controllers/Mastodon/InstanceController.cs b/Iceshrimp.Backend/Controllers/Mastodon/InstanceController.cs index 2e993d20..8d288f18 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/InstanceController.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/InstanceController.cs @@ -36,18 +36,23 @@ public class InstanceController( var noteCount = await db.Notes.LongCountAsync(p => p.UserHost == null); var instanceCount = await db.Instances.LongCountAsync(); - var (instanceName, instanceDescription, adminContact) = + var (instanceName, instanceDescription, adminContact, bannerId) = await meta.GetManyAsync(MetaEntity.InstanceName, MetaEntity.InstanceDescription, - MetaEntity.AdminContactEmail); + MetaEntity.AdminContactEmail, MetaEntity.BannerFileId); // can't merge with above call since they're all nullable and this is not. var vapidKey = await meta.GetAsync(MetaEntity.VapidPublicKey); + var banner = await db.DriveFiles.Where(p => p.Id == bannerId) + .Select(p => p.PublicUrl ?? p.RawAccessUrl) + .FirstOrDefaultAsync(); + return new InstanceInfoV1Response(config.Value, instanceName, instanceDescription, adminContact) { Stats = new InstanceStats(userCount, noteCount, instanceCount), Pleroma = new PleromaInstanceExtensions { VapidPublicKey = vapidKey, Metadata = new InstanceMetadata() }, - Rules = await GetRules() + Rules = await GetRules(), + ThumbnailUrl = banner }; } @@ -61,20 +66,40 @@ public class InstanceController( && !Constants.SystemUsers.Contains(p.UsernameLower) && p.LastActiveDate > cutoff); - var (instanceName, instanceDescription, adminContact, iconId) = + var (instanceName, instanceDescription, adminContact, iconId, bannerId) = await meta.GetManyAsync(MetaEntity.InstanceName, MetaEntity.InstanceDescription, - MetaEntity.AdminContactEmail, MetaEntity.IconFileId); + MetaEntity.AdminContactEmail, MetaEntity.IconFileId, MetaEntity.BannerFileId); var favicon = await db.DriveFiles.Where(p => p.Id == iconId) .Select(p => new InstanceIcon(p.PublicUrl ?? p.RawAccessUrl, p.Properties.Width ?? 128, p.Properties.Height ?? 128)) .FirstOrDefaultAsync(); + List icons = favicon != null + ? [favicon] + : + [ + new + InstanceIcon($"https://{config.Value.Instance.WebDomain}/_content/Iceshrimp.Assets.Branding/192.png", + 192, 192), + new + InstanceIcon($"https://{config.Value.Instance.WebDomain}/_content/Iceshrimp.Assets.Branding/512.png", + 512, 512) + ]; + + // Mastodon expects an instance thumbnail, the mail wordmark isn't ideal but it's the closest thing ww have for a fallback + var banner = await db.DriveFiles.Where(p => p.Id == bannerId) + .Select(p => new InstanceThumbnail(p.PublicUrl ?? p.RawAccessUrl, p.Blurhash)) + .FirstOrDefaultAsync() + ?? new + InstanceThumbnail($"https://{config.Value.Instance.WebDomain}/_content/Iceshrimp.Assets.Branding/mail-wordmark.png", + null); return new InstanceInfoV2Response(config.Value, instanceName, instanceDescription, adminContact) { Usage = new InstanceUsage { Users = new InstanceUsersUsage { ActiveMonth = activeMonth } }, Rules = await GetRules(), - Icons = favicon != null ? [favicon] : [] + Icons = icons, + Thumbnail = banner }; } diff --git a/Iceshrimp.Backend/Controllers/Mastodon/Schemas/InstanceInfoV1Response.cs b/Iceshrimp.Backend/Controllers/Mastodon/Schemas/InstanceInfoV1Response.cs index 335e0d6c..3c077fa6 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/Schemas/InstanceInfoV1Response.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/Schemas/InstanceInfoV1Response.cs @@ -40,6 +40,8 @@ public class InstanceInfoV1Response( [J("rules")] public required List Rules { get; set; } + [J("thumbnail")] public required string? ThumbnailUrl { get; set; } + //TODO: add the rest } diff --git a/Iceshrimp.Backend/Controllers/Mastodon/Schemas/InstanceInfoV2Response.cs b/Iceshrimp.Backend/Controllers/Mastodon/Schemas/InstanceInfoV2Response.cs index 38095a45..c5357d6d 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/Schemas/InstanceInfoV2Response.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/Schemas/InstanceInfoV2Response.cs @@ -30,6 +30,8 @@ public class InstanceInfoV2Response( [J("rules")] public required List Rules { get; set; } [J("icon")] public required List Icons { get; set; } + + [J("thumbnail")] public required InstanceThumbnail Thumbnail { get; set; } //TODO: add the rest } @@ -84,4 +86,10 @@ public class InstanceIcon(string src, int width, int height) { [J("src")] public string Url => src; [J("size")] public string Size => $"{width}x{height}"; +} + +public class InstanceThumbnail(string url, string? blurhash) +{ + [J("url")] public string Url => url; + [J("blurhash")] public string? Blurhash => blurhash; } \ No newline at end of file