From 6cba70ee127fb4ecbdebeeabcb771ae0a223c915 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Mon, 29 Dec 2025 00:08:16 +0800 Subject: [PATCH] :sparkles: Activity pub also support XML webfinger --- .../ActivityPubDiscoveryService.cs | 86 +++++++++++++++++-- 1 file changed, 79 insertions(+), 7 deletions(-) diff --git a/DysonNetwork.Sphere/ActivityPub/ActivityPubDiscoveryService.cs b/DysonNetwork.Sphere/ActivityPub/ActivityPubDiscoveryService.cs index 1925b1b..0bfb855 100644 --- a/DysonNetwork.Sphere/ActivityPub/ActivityPubDiscoveryService.cs +++ b/DysonNetwork.Sphere/ActivityPub/ActivityPubDiscoveryService.cs @@ -2,6 +2,7 @@ using DysonNetwork.Shared.Models; using Microsoft.EntityFrameworkCore; using System.Text.Json; using System.Text.RegularExpressions; +using System.Xml.Linq; namespace DysonNetwork.Sphere.ActivityPub; @@ -82,18 +83,57 @@ public partial class ActivityPubDiscoveryService( return null; } - var json = await response.Content.ReadAsStringAsync(); - logger.LogDebug("Webfinger response from {Url}: {Json}", webfingerUrl, json); + var contentType = response.Content.Headers.ContentType?.MediaType; + logger.LogDebug("Webfinger response Content-Type: {ContentType}", contentType); + var content = await response.Content.ReadAsStringAsync(); + logger.LogDebug("Webfinger response from {Url}: {Content}", webfingerUrl, content); + + string? actorUri; + + if (contentType?.Contains("json") == true) + { + actorUri = ParseJsonWebfingerResponse(content, webfingerUrl); + } + else if (contentType?.Contains("xml") == true || content.TrimStart().StartsWith("(json); if (webfingerData?.Links == null) { - logger.LogWarning("Invalid Webfinger response from {Url}", webfingerUrl); + logger.LogWarning("Invalid JSON Webfinger response from {Url}", sourceUrl); return null; } - logger.LogDebug("Found {LinkCount} links in Webfinger response", webfingerData.Links.Count); + logger.LogDebug("Found {LinkCount} links in JSON Webfinger response", webfingerData.Links.Count); foreach (var link in webfingerData.Links) { logger.LogDebug("Link: rel={Rel}, type={Type}, href={Href}", link.Rel, link.Type, link.Href); @@ -104,16 +144,48 @@ public partial class ActivityPubDiscoveryService( if (selfLink == null) { - logger.LogWarning("No self link found in Webfinger response from {Url}", webfingerUrl); + logger.LogWarning("No self link found in JSON Webfinger response from {Url}", sourceUrl); return null; } - logger.LogInformation("Found actor URI via Webfinger: {ActorUri}", selfLink.Href); return selfLink.Href; } catch (Exception ex) { - logger.LogError(ex, "Error querying Webfinger for {Username}@{Domain}", username, domain); + logger.LogError(ex, "Error parsing JSON Webfinger response from {Url}", sourceUrl); + return null; + } + } + + private string? ParseXmlWebfingerResponse(string xml, string sourceUrl) + { + try + { + var xDoc = XDocument.Parse(xml); + var xNamespace = XNamespace.Get("http://docs.oasis-open.org/ns/xri/xrd-1.0"); + + var links = xDoc.Descendants(xNamespace + "Link").ToList(); + logger.LogDebug("Found {LinkCount} links in XML Webfinger response", links.Count); + + foreach (var link in links) + { + var rel = link.Attribute("rel")?.Value; + var type = link.Attribute("type")?.Value; + var href = link.Attribute("href")?.Value; + logger.LogDebug("XML Link: rel={Rel}, type={Type}, href={Href}", rel, type, href); + + if (rel == "self" && type == "application/activity+json" && href != null) + { + return href; + } + } + + logger.LogWarning("No self link found in XML Webfinger response from {Url}", sourceUrl); + return null; + } + catch (Exception ex) + { + logger.LogError(ex, "Error parsing XML Webfinger response from {Url}", sourceUrl); return null; } }