[backend/federation] Get favicon and icon for remote instances
This commit is contained in:
parent
6975fa9495
commit
cfd7d62777
1 changed files with 63 additions and 2 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
using AngleSharp.Html.Parser;
|
||||||
using AsyncKeyedLock;
|
using AsyncKeyedLock;
|
||||||
using Iceshrimp.Backend.Core.Database;
|
using Iceshrimp.Backend.Core.Database;
|
||||||
using Iceshrimp.Backend.Core.Database.Tables;
|
using Iceshrimp.Backend.Core.Database.Tables;
|
||||||
|
@ -63,14 +64,15 @@ public class InstanceService(
|
||||||
{
|
{
|
||||||
instance.InfoUpdatedAt = DateTime.UtcNow;
|
instance.InfoUpdatedAt = DateTime.UtcNow;
|
||||||
var nodeinfo = await GetNodeInfoAsync(webDomain);
|
var nodeinfo = await GetNodeInfoAsync(webDomain);
|
||||||
|
var icons = await GetIconsAsync(webDomain);
|
||||||
if (nodeinfo != null)
|
if (nodeinfo != null)
|
||||||
{
|
{
|
||||||
instance.Name = nodeinfo.Metadata?.NodeName;
|
instance.Name = nodeinfo.Metadata?.NodeName;
|
||||||
instance.Description = nodeinfo.Metadata?.NodeDescription;
|
instance.Description = nodeinfo.Metadata?.NodeDescription;
|
||||||
//instance.FaviconUrl = TODO,
|
instance.FaviconUrl = icons.FaviconUrl;
|
||||||
//instance.FollowersCount = TODO,
|
//instance.FollowersCount = TODO,
|
||||||
//instance.FollowingCount = TODO,
|
//instance.FollowingCount = TODO,
|
||||||
//instance.IconUrl = TODO,
|
instance.IconUrl = icons.IconUrl;
|
||||||
instance.MaintainerName = nodeinfo.Metadata?.Maintainer?.Name;
|
instance.MaintainerName = nodeinfo.Metadata?.Maintainer?.Name;
|
||||||
instance.MaintainerEmail = nodeinfo.Metadata?.Maintainer?.Email;
|
instance.MaintainerEmail = nodeinfo.Metadata?.Maintainer?.Email;
|
||||||
instance.OpenRegistrations = nodeinfo.OpenRegistrations;
|
instance.OpenRegistrations = nodeinfo.OpenRegistrations;
|
||||||
|
@ -92,6 +94,65 @@ public class InstanceService(
|
||||||
return await GetUpdatedInstanceMetadataAsync(user.Host, new Uri(user.Uri).Host);
|
return await GetUpdatedInstanceMetadataAsync(user.Host, new Uri(user.Uri).Host);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<(string? FaviconUrl, string? IconUrl)> GetIconsAsync(string webDomain)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const int maxLength = 1_000_000;
|
||||||
|
var res = await httpClient.GetAsync($"https://{webDomain}", HttpCompletionOption.ResponseHeadersRead);
|
||||||
|
|
||||||
|
if (res is not
|
||||||
|
{
|
||||||
|
IsSuccessStatusCode: true,
|
||||||
|
Content.Headers: { ContentType.MediaType: "text/html", ContentLength: null or <= maxLength }
|
||||||
|
})
|
||||||
|
return (null, null);
|
||||||
|
|
||||||
|
var contentLength = res.Content.Headers.ContentLength;
|
||||||
|
var stream = await res.Content.ReadAsStreamAsync()
|
||||||
|
.ContinueWithResult(p => p.GetSafeStreamOrNullAsync(maxLength, contentLength));
|
||||||
|
|
||||||
|
if (stream == Stream.Null) return (null, null);
|
||||||
|
|
||||||
|
var document = await new HtmlParser().ParseDocumentAsync(stream);
|
||||||
|
|
||||||
|
var faviconUrl = document.Head?.Children.Last(e => e.NodeName.ToLower() == "link"
|
||||||
|
&& (e.GetAttribute("rel")
|
||||||
|
?.Contains("icon")
|
||||||
|
?? false))
|
||||||
|
.GetAttribute("href");
|
||||||
|
|
||||||
|
if (faviconUrl == null)
|
||||||
|
{
|
||||||
|
var favicon = await httpClient.GetAsync($"https://{webDomain}/favicon.ico");
|
||||||
|
if (favicon.IsSuccessStatusCode) faviconUrl = $"https://{webDomain}/favicon.ico";
|
||||||
|
}
|
||||||
|
|
||||||
|
var iconUrl = document.Head?.Children.Last(e => e.NodeName.ToLower() == "link"
|
||||||
|
&& (e.GetAttribute("rel")
|
||||||
|
?.Contains("apple-touch-icon-precomposed")
|
||||||
|
?? false)
|
||||||
|
|| (e.GetAttribute("rel")
|
||||||
|
?.Contains("apple-touch-icon")
|
||||||
|
?? false)
|
||||||
|
|| (e.GetAttribute("rel")
|
||||||
|
?.Contains("icon")
|
||||||
|
?? false))
|
||||||
|
.GetAttribute("href");
|
||||||
|
|
||||||
|
var baseUri = new Uri($"https://{webDomain}");
|
||||||
|
|
||||||
|
return (
|
||||||
|
faviconUrl != null ? new Uri(baseUri, faviconUrl).ToString() : null,
|
||||||
|
iconUrl != null ? new Uri(baseUri, iconUrl).ToString() : null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return (null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<NodeInfoResponse?> GetNodeInfoAsync(string webDomain)
|
private async Task<NodeInfoResponse?> GetNodeInfoAsync(string webDomain)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
Loading…
Add table
Reference in a new issue