docs: Update documentation for 145 files

Generated by AurionDocs
Job ID: 934f8c39-8082-4942-8d17-72ed8f5f8d50
Source commit: 40aea9a
This commit is contained in:
Hue
2026-07-23 11:44:20 +02:00
parent 40aea9a04b
commit 607217b314
144 changed files with 5098 additions and 6498 deletions
@@ -8,86 +8,13 @@
```mermaid
%%{init: {'theme':'base','themeVariables':{'background':'#faf7ef','primaryColor':'#f0e2c2','primaryTextColor':'#1f2840','primaryBorderColor':'#8a7548','secondaryColor':'#d9efec','secondaryBorderColor':'#1d8a80','secondaryTextColor':'#1f2840','tertiaryColor':'#f2ebd8','tertiaryBorderColor':'#8a7548','tertiaryTextColor':'#1f2840','lineColor':'#1d8a80','titleColor':'#1f2840','fontSize':'14px','edgeLabelBackground':'#faf7ef','clusterBkg':'#f2ebd8','clusterBorder':'#8a7548','actorBkg':'#f0e2c2','actorBorder':'#8a7548','actorTextColor':'#1f2840','actorLineColor':'#8a7548','signalColor':'#1d8a80','signalTextColor':'#1f2840','activationBkgColor':'#d9efec','activationBorderColor':'#1d8a80','noteBkgColor':'#f2ebd8','noteBorderColor':'#8a7548','noteTextColor':'#1f2840','labelBoxBkgColor':'#f0e2c2','labelBoxBorderColor':'#8a7548','labelTextColor':'#1f2840','transitionColor':'#1d8a80','transitionLabelColor':'#1f2840','stateLabelColor':'#1f2840','altBackground':'#f2ebd8'}}}%%
flowchart TB
Start["Start"]
Extract["ExtractUrls(content) -> urls"]
CheckUrls["urls.Count == 0?"]
ReturnNullNoUrls["Return null (no URLs found)"]
InitEmbeds["Create empty List#60;EmbedDto#62; embeds"]
ForEach["For each url in urls"]
CallFetch["Call FetchEmbedForUrlAsync(url)"]
ReturnNullFromFetch["Returned null -> continue"]
AddEmbed["Add EmbedDto to embeds"]
CatchLog["Catch Exception -> LogDebug and continue"]
AfterLoop["All URLs processed"]
ReturnDecision["embeds.Count > 0?"]
ReturnEmbeds["Return embeds"]
ReturnNullAll["Return null (no successful embeds)"]
LinkEmbedService["TryGetEmbedsAsync: ExtractUrls content; if no URLs -> return null. For each URL: call FetchEmbedForUrlAsync -> validate absolute URI, allow http or https, skip private hosts; create CancellationTokenSource using HubConstants, send GET with HttpClient 'OgFetch' and HttpCompletionOption.ResponseHeadersRead; if non-success status -> skip; ensure Content-Type starts with text/html; read limited HTML; parse OG tags; determine title with og:title fallback to <title>; if no title -> skip; else build EmbedDto and add to results. Catch exceptions and LogDebug. Return embeds list or null"]
HubConstants["HubConstants: EmbedFetchTimeoutSeconds, EmbedMaxHtmlBytes, EmbedMaxDescription"]
EmbedDto["EmbedDto: represents successful OG embed data"]
subgraph FetchEmbedForUrlAsync
F1["Try Uri.TryCreate(url, Absolute)"]
F1_no["Return null (invalid uri)"]
F2["Check scheme is http or https"]
F2_no["Return null (unsupported scheme)"]
F3["IsPrivateHost(uri)?"]
F3_no["Return null (private host)"]
F4["Create CTS with HubConstants.EmbedFetchTimeoutSeconds"]
F5["Create HTTP client 'OgFetch'"]
F6["Send GET request, get response"]
F7["response.IsSuccessStatusCode?"]
F7_no["Return null (unsuccessful status)"]
F8["Content-Type starts with #quot;text/html#quot;?"]
F8_no["Return null (non-html content)"]
F9["Read limited HTML (HubConstants.EmbedMaxHtmlBytes)"]
F9_empty["Return null (empty or whitespace html)"]
F10["Parse OG tags, get title or fall back to #60;title#62;"]
F10_no["Return null (no title)"]
F11["Build EmbedDto and return"]
end
Start --> Extract
Extract --> CheckUrls
CheckUrls -->|"yes"| ReturnNullNoUrls
CheckUrls -->|"no"| InitEmbeds
InitEmbeds --> ForEach
ForEach --> CallFetch
CallFetch -->|"throws"| CatchLog
CallFetch -->|"null"| ReturnNullFromFetch
CallFetch -->|"EmbedDto"| AddEmbed
ReturnNullFromFetch --> ForEach
AddEmbed --> ForEach
CatchLog --> ForEach
ForEach -->|"done"| AfterLoop
AfterLoop --> ReturnDecision
ReturnDecision -->|"yes"| ReturnEmbeds
ReturnDecision -->|"no"| ReturnNullAll
CallFetch --> F1
F1 -->|"no"| F1_no
F1 -->|"yes"| F2
F2 -->|"no"| F2_no
F2 -->|"yes"| F3
F3 -->|"true"| F3_no
F3 -->|"false"| F4
F4 --> F5
F5 --> F6
F6 --> F7
F7 -->|"no"| F7_no
F7 -->|"yes"| F8
F8 -->|"no"| F8_no
F8 -->|"yes"| F9
F9 -->|"empty"| F9_empty
F9 -->|"has html"| F10
F10 -->|"no"| F10_no
F10 -->|"yes"| F11
F1_no --> ReturnNullFromFetch
F2_no --> ReturnNullFromFetch
F3_no --> ReturnNullFromFetch
F7_no --> ReturnNullFromFetch
F8_no --> ReturnNullFromFetch
F9_empty --> ReturnNullFromFetch
F10_no --> ReturnNullFromFetch
F11 --> AddEmbed
LinkEmbedService -->|"reads timeouts and limits"| HubConstants
LinkEmbedService -->|"creates and adds successful EmbedDto"| EmbedDto
LinkEmbedService -->|"foreach URL (loop)"| LinkEmbedService
```
```csharp
@@ -95,30 +22,13 @@ public partial class LinkEmbedService
```
Scans a piece of message text for URLs and attempts to produce lightweight link preview data (EmbedDto) by fetching and parsing Open Graph and common HTML metadata. Use TryGetEmbedsAsync when you need server-side link previews for chat messages and want a defensive, timeout- and size-limited fetch that never throws (it logs failures and returns null when no usable embeds are found).
Detects and fetches Open Graph-style embed metadata for any URLs found in a piece of message `content`. Use `LinkEmbedService` (via its `TryGetEmbedsAsync` method) when you want a best-effort, non-throwing attempt to produce [`EmbedDto`](../../EchoHub.Core/DTOs/ChatDtos.cs.md) objects for links inside user messages — for example, to show link previews — and you want network, size and privacy protections applied automatically.
## Remarks
LinkEmbedService centralizes the logic for discovering URLs in a message and converting remote HTML metadata into EmbedDto instances suitable for display. It is intentionally defensive: only absolute http/https URLs are considered, private hosts are skipped, fetches are limited by a cancellation timeout and a maximum HTML byte count (HubConstants), and only text/html responses are parsed. Errors during individual fetches are caught and logged at debug level so the caller observes either a list of successful embeds or null (no useful embeds).
## Example
```csharp
// Given an instance of LinkEmbedService (typically from DI):
var embeds = await linkEmbedService.TryGetEmbedsAsync(messageContent);
if (embeds is null)
{
// No embeds found or all fetch attempts failed.
}
else
{
Console.WriteLine($"Found {embeds.Count} embeds");
foreach (var embed in embeds)
{
// render embed in UI or pass to presentation layer
}
}
```
`LinkEmbedService` centralizes link-preview logic so callers do not have to implement URL extraction, host-safety checks, HTTP fetching, HTML-size limits, or Open Graph parsing themselves. The public `TryGetEmbedsAsync` method returns `null` when no useful embed data is available (either because no URLs were found or all fetch attempts failed) and never throws; individual fetch failures are caught and logged at debug level. Internally it calls the private `FetchEmbedForUrlAsync` for each URL which enforces absolute `http`/`https` URIs, rejects private hosts via `IsPrivateHost`, uses an `IHttpClientFactory`-created client named `"OgFetch"`, applies a `CancellationTokenSource` timeout (`HubConstants.EmbedFetchTimeoutSeconds`), requires a `text/html` response, bounds the HTML read size (`HubConstants.EmbedMaxHtmlBytes`), extracts Open Graph tags (falling back to the `<title>` tag), decodes HTML entities with `WebUtility.HtmlDecode`, and truncates long descriptions to `HubConstants.EmbedMaxDescriptionLength`.
## Notes
- TryGetEmbedsAsync returns null when no URLs are present or when all fetches fail; it does not return an empty list in those cases—check for null before iterating.
- The service expects an IHttpClientFactory and creates a client with the name "OgFetch"; ensure your HttpClient configuration (handlers, DNS/timeout policies) is appropriate for remote HTML fetches.
- HTML metadata extraction is heuristic: it uses Open Graph tags, falls back to a <title> regex, reads only the first N bytes of HTML, and truncates long descriptions per HubConstants. Consumers should treat returned fields as untrusted display content and apply any necessary sanitization in the UI layer.
- The service expects an `IHttpClientFactory` client named `"OgFetch"` to be configured; network policy (proxies, handlers) should be applied on that named client rather than relying on this class to set HTTP options.
- Fetching is constrained by time and size: a cancellation timeout (`HubConstants.EmbedFetchTimeoutSeconds`) and a maximum number of HTML bytes (`HubConstants.EmbedMaxHtmlBytes`) are enforced; pages that exceed these limits may yield no embed.
- Only absolute `http`/`https` URLs are considered and private/internal hosts are explicitly ignored by `IsPrivateHost`; the method will return `null` instead of an [`EmbedDto`](../../EchoHub.Core/DTOs/ChatDtos.cs.md) for such URLs.
- Failures during individual URL fetches are swallowed (logged at debug) so `TryGetEmbedsAsync` remains non-throwing for callers — check logs when embeds are unexpectedly missing.