This commit is contained in:
HueByte
2026-02-24 21:03:14 +00:00
parent bd22be4181
commit 5031bf0e11
56 changed files with 8746 additions and 374 deletions
@@ -0,0 +1,660 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Class BackupInfo | EchoHub Documentation </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Class BackupInfo | EchoHub Documentation ">
<link rel="icon" href="../../images/hue_icon.svg">
<link rel="stylesheet" href="../../public/docfx.min.css">
<link rel="stylesheet" href="../../public/main.css">
<meta name="docfx:navrel" content="../../toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../../">
<meta name="docfx:docurl" content="https://github.com/HueByte/EchoHub/new/master/apiSpec/new?filename=EchoHub_Client_Services_BackupInfo.md&amp;value=---%0Auid%3A%20EchoHub.Client.Services.BackupInfo%0Asummary%3A%20&#39;*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax&#39;%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="ManagedReference">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../../index.html">
<img id="logo" class="svg" src="../../images/hue_icon.svg" alt="EchoHub">
EchoHub
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="EchoHub.Client.Services.BackupInfo">
<h1 id="EchoHub_Client_Services_BackupInfo" data-uid="EchoHub.Client.Services.BackupInfo" class="text-break">
Class BackupInfo <a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/UpdateBackupService.cs"><i class="bi bi-code-slash"></i></a>
</h1>
<div class="facts text-secondary">
<dl><dt>Namespace</dt><dd><a class="xref" href="EchoHub.html">EchoHub</a>.<a class="xref" href="EchoHub.Client.html">Client</a>.<a class="xref" href="EchoHub.Client.Services.html">Services</a></dd></dl>
<dl><dt>Assembly</dt><dd>EchoHub.Client.dll</dd></dl>
</div>
<div class="markdown summary"></div>
<div class="markdown conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public record BackupInfo : IEquatable&lt;BackupInfo&gt;</code></pre>
</div>
<dl class="typelist inheritance">
<dt>Inheritance</dt>
<dd>
<div><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object">object</a></div>
<div><span class="xref">BackupInfo</span></div>
</dd>
</dl>
<dl class="typelist implements">
<dt>Implements</dt>
<dd>
<div><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.iequatable-1">IEquatable</a>&lt;<a class="xref" href="EchoHub.Client.Services.BackupInfo.html">BackupInfo</a>&gt;</div>
</dd>
</dl>
<dl class="typelist inheritedMembers">
<dt>Inherited Members</dt>
<dd>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.gettype">object.GetType()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.memberwiseclone">object.MemberwiseClone()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object-system-object)">object.Equals(object, object)</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.referenceequals">object.ReferenceEquals(object, object)</a>
</div>
</dd></dl>
<h2 class="section" id="constructors">Constructors
</h2>
<a id="EchoHub_Client_Services_BackupInfo__ctor_" data-uid="EchoHub.Client.Services.BackupInfo.#ctor*"></a>
<h3 id="EchoHub_Client_Services_BackupInfo__ctor_EchoHub_Client_Services_BackupInfo_" data-uid="EchoHub.Client.Services.BackupInfo.#ctor(EchoHub.Client.Services.BackupInfo)">
BackupInfo(BackupInfo)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/UpdateBackupService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">protected BackupInfo(BackupInfo original)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>original</code> <a class="xref" href="EchoHub.Client.Services.BackupInfo.html">BackupInfo</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Client_Services_BackupInfo__ctor_" data-uid="EchoHub.Client.Services.BackupInfo.#ctor*"></a>
<h3 id="EchoHub_Client_Services_BackupInfo__ctor_System_String_System_String_System_DateTimeOffset_" data-uid="EchoHub.Client.Services.BackupInfo.#ctor(System.String,System.String,System.DateTimeOffset)">
BackupInfo(string, string, DateTimeOffset)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/UpdateBackupService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public BackupInfo(string Version, string AppDirectory, DateTimeOffset CreatedAt)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>Version</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dt><code>AppDirectory</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dt><code>CreatedAt</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.datetimeoffset">DateTimeOffset</a></dt>
<dd></dd>
</dl>
<h2 class="section" id="properties">Properties
</h2>
<a id="EchoHub_Client_Services_BackupInfo_AppDirectory_" data-uid="EchoHub.Client.Services.BackupInfo.AppDirectory*"></a>
<h3 id="EchoHub_Client_Services_BackupInfo_AppDirectory" data-uid="EchoHub.Client.Services.BackupInfo.AppDirectory">
AppDirectory
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/UpdateBackupService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public string AppDirectory { get; init; }</code></pre>
</div>
<h4 class="section">Property Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Client_Services_BackupInfo_CreatedAt_" data-uid="EchoHub.Client.Services.BackupInfo.CreatedAt*"></a>
<h3 id="EchoHub_Client_Services_BackupInfo_CreatedAt" data-uid="EchoHub.Client.Services.BackupInfo.CreatedAt">
CreatedAt
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/UpdateBackupService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public DateTimeOffset CreatedAt { get; init; }</code></pre>
</div>
<h4 class="section">Property Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.datetimeoffset">DateTimeOffset</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Client_Services_BackupInfo_EqualityContract_" data-uid="EchoHub.Client.Services.BackupInfo.EqualityContract*"></a>
<h3 id="EchoHub_Client_Services_BackupInfo_EqualityContract" data-uid="EchoHub.Client.Services.BackupInfo.EqualityContract">
EqualityContract
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/UpdateBackupService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">protected virtual Type EqualityContract { get; }</code></pre>
</div>
<h4 class="section">Property Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.type">Type</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Client_Services_BackupInfo_Version_" data-uid="EchoHub.Client.Services.BackupInfo.Version*"></a>
<h3 id="EchoHub_Client_Services_BackupInfo_Version" data-uid="EchoHub.Client.Services.BackupInfo.Version">
Version
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/UpdateBackupService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public string Version { get; init; }</code></pre>
</div>
<h4 class="section">Property Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h2 class="section" id="methods">Methods
</h2>
<a id="EchoHub_Client_Services_BackupInfo_Deconstruct_" data-uid="EchoHub.Client.Services.BackupInfo.Deconstruct*"></a>
<h3 id="EchoHub_Client_Services_BackupInfo_Deconstruct_System_String__System_String__System_DateTimeOffset__" data-uid="EchoHub.Client.Services.BackupInfo.Deconstruct(System.String@,System.String@,System.DateTimeOffset@)">
Deconstruct(out string, out string, out DateTimeOffset)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/UpdateBackupService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public void Deconstruct(out string Version, out string AppDirectory, out DateTimeOffset CreatedAt)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>Version</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dt><code>AppDirectory</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dt><code>CreatedAt</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.datetimeoffset">DateTimeOffset</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Client_Services_BackupInfo_Equals_" data-uid="EchoHub.Client.Services.BackupInfo.Equals*"></a>
<h3 id="EchoHub_Client_Services_BackupInfo_Equals_EchoHub_Client_Services_BackupInfo_" data-uid="EchoHub.Client.Services.BackupInfo.Equals(EchoHub.Client.Services.BackupInfo)">
Equals(BackupInfo?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/UpdateBackupService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public virtual bool Equals(BackupInfo? other)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>other</code> <a class="xref" href="EchoHub.Client.Services.BackupInfo.html">BackupInfo</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.boolean">bool</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Client_Services_BackupInfo_Equals_" data-uid="EchoHub.Client.Services.BackupInfo.Equals*"></a>
<h3 id="EchoHub_Client_Services_BackupInfo_Equals_System_Object_" data-uid="EchoHub.Client.Services.BackupInfo.Equals(System.Object)">
Equals(object?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/UpdateBackupService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public override bool Equals(object? obj)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>obj</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object">object</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.boolean">bool</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Client_Services_BackupInfo_GetHashCode_" data-uid="EchoHub.Client.Services.BackupInfo.GetHashCode*"></a>
<h3 id="EchoHub_Client_Services_BackupInfo_GetHashCode" data-uid="EchoHub.Client.Services.BackupInfo.GetHashCode">
GetHashCode()
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/UpdateBackupService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public override int GetHashCode()</code></pre>
</div>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.int32">int</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Client_Services_BackupInfo_PrintMembers_" data-uid="EchoHub.Client.Services.BackupInfo.PrintMembers*"></a>
<h3 id="EchoHub_Client_Services_BackupInfo_PrintMembers_System_Text_StringBuilder_" data-uid="EchoHub.Client.Services.BackupInfo.PrintMembers(System.Text.StringBuilder)">
PrintMembers(StringBuilder)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/UpdateBackupService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">protected virtual bool PrintMembers(StringBuilder builder)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>builder</code> <span class="xref">StringBuilder</span></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.boolean">bool</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Client_Services_BackupInfo_ToString_" data-uid="EchoHub.Client.Services.BackupInfo.ToString*"></a>
<h3 id="EchoHub_Client_Services_BackupInfo_ToString" data-uid="EchoHub.Client.Services.BackupInfo.ToString">
ToString()
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/UpdateBackupService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public override string ToString()</code></pre>
</div>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h2 class="section" id="operators">Operators
</h2>
<a id="EchoHub_Client_Services_BackupInfo_op_Equality_" data-uid="EchoHub.Client.Services.BackupInfo.op_Equality*"></a>
<h3 id="EchoHub_Client_Services_BackupInfo_op_Equality_EchoHub_Client_Services_BackupInfo_EchoHub_Client_Services_BackupInfo_" data-uid="EchoHub.Client.Services.BackupInfo.op_Equality(EchoHub.Client.Services.BackupInfo,EchoHub.Client.Services.BackupInfo)">
operator ==(BackupInfo?, BackupInfo?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/UpdateBackupService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static bool operator ==(BackupInfo? left, BackupInfo? right)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>left</code> <a class="xref" href="EchoHub.Client.Services.BackupInfo.html">BackupInfo</a></dt>
<dd></dd>
<dt><code>right</code> <a class="xref" href="EchoHub.Client.Services.BackupInfo.html">BackupInfo</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.boolean">bool</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Client_Services_BackupInfo_op_Inequality_" data-uid="EchoHub.Client.Services.BackupInfo.op_Inequality*"></a>
<h3 id="EchoHub_Client_Services_BackupInfo_op_Inequality_EchoHub_Client_Services_BackupInfo_EchoHub_Client_Services_BackupInfo_" data-uid="EchoHub.Client.Services.BackupInfo.op_Inequality(EchoHub.Client.Services.BackupInfo,EchoHub.Client.Services.BackupInfo)">
operator !=(BackupInfo?, BackupInfo?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/UpdateBackupService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static bool operator !=(BackupInfo? left, BackupInfo? right)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>left</code> <a class="xref" href="EchoHub.Client.Services.BackupInfo.html">BackupInfo</a></dt>
<dd></dd>
<dt><code>right</code> <a class="xref" href="EchoHub.Client.Services.BackupInfo.html">BackupInfo</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.boolean">bool</a></dt>
<dd></dd>
</dl>
</article>
<div class="contribution d-print-none">
<a href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/UpdateBackupService.cs" class="edit-link">Edit this page</a>
</div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<div class='footer-custom'><div class='footer-inner'><span class='footer-brand'>EchoHub</span><span class='footer-sep'>&middot;</span><a href='https://github.com/HueByte/EchoHub'>GitHub</a><span class='footer-sep'>&middot;</span><a href='https://echohub.voidcube.cloud'>Website</a><span class='footer-sep'>&middot;</span><span class='footer-credit'>Built with <a href='https://dotnet.github.io/docfx'>DocFX</a></span></div></div>
</div>
</div>
</footer>
</body>
</html>
@@ -828,7 +828,7 @@ Class EchoHubConnection <a class="header-action link-secondary" title="View sou
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public event Action&lt;string, string&gt;? OnUserJoined</code></pre>
<pre><code class="lang-csharp hljs">public event Action&lt;string, string, UserPresenceDto?&gt;? OnUserJoined</code></pre>
</div>
@@ -838,7 +838,7 @@ Class EchoHubConnection <a class="header-action link-secondary" title="View sou
<h4 class="section">Event Type</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.action-2">Action</a>&lt;<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a>, <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a>&gt;</dt>
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.action-3">Action</a>&lt;<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a>, <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a>, <a class="xref" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/ProfileDtos.cs">UserPresenceDto</a>&gt;</dt>
<dd></dd>
</dl>
@@ -0,0 +1,211 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Class PathSetup | EchoHub Documentation </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Class PathSetup | EchoHub Documentation ">
<meta name="description" content="Ensures the application&#39;s directory is on the system PATH so users can run &#39;echohub&#39; from any terminal session.">
<link rel="icon" href="../../images/hue_icon.svg">
<link rel="stylesheet" href="../../public/docfx.min.css">
<link rel="stylesheet" href="../../public/main.css">
<meta name="docfx:navrel" content="../../toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../../">
<meta name="docfx:docurl" content="https://github.com/HueByte/EchoHub/new/master/apiSpec/new?filename=EchoHub_Client_Services_PathSetup.md&amp;value=---%0Auid%3A%20EchoHub.Client.Services.PathSetup%0Asummary%3A%20&#39;*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax&#39;%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="ManagedReference">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../../index.html">
<img id="logo" class="svg" src="../../images/hue_icon.svg" alt="EchoHub">
EchoHub
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="EchoHub.Client.Services.PathSetup">
<h1 id="EchoHub_Client_Services_PathSetup" data-uid="EchoHub.Client.Services.PathSetup" class="text-break">
Class PathSetup <a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/PathSetup.cs"><i class="bi bi-code-slash"></i></a>
</h1>
<div class="facts text-secondary">
<dl><dt>Namespace</dt><dd><a class="xref" href="EchoHub.html">EchoHub</a>.<a class="xref" href="EchoHub.Client.html">Client</a>.<a class="xref" href="EchoHub.Client.Services.html">Services</a></dd></dl>
<dl><dt>Assembly</dt><dd>EchoHub.Client.dll</dd></dl>
</div>
<div class="markdown summary"><p>Ensures the application's directory is on the system PATH so users
can run 'echohub' from any terminal session.</p>
</div>
<div class="markdown conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static class PathSetup</code></pre>
</div>
<dl class="typelist inheritance">
<dt>Inheritance</dt>
<dd>
<div><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object">object</a></div>
<div><span class="xref">PathSetup</span></div>
</dd>
</dl>
<dl class="typelist inheritedMembers">
<dt>Inherited Members</dt>
<dd>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.gettype">object.GetType()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.memberwiseclone">object.MemberwiseClone()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.tostring">object.ToString()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object)">object.Equals(object)</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object-system-object)">object.Equals(object, object)</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.referenceequals">object.ReferenceEquals(object, object)</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.gethashcode">object.GetHashCode()</a>
</div>
</dd></dl>
<h2 class="section" id="methods">Methods
</h2>
<a id="EchoHub_Client_Services_PathSetup_EnsureOnPath_" data-uid="EchoHub.Client.Services.PathSetup.EnsureOnPath*"></a>
<h3 id="EchoHub_Client_Services_PathSetup_EnsureOnPath" data-uid="EchoHub.Client.Services.PathSetup.EnsureOnPath">
EnsureOnPath()
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/PathSetup.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>Checks if the app directory is on PATH; if not, adds it persistently.
On Windows: modifies user-level PATH environment variable.
On Linux/macOS: appends an export line to shell profile files.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static void EnsureOnPath()</code></pre>
</div>
</article>
<div class="contribution d-print-none">
<a href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/PathSetup.cs" class="edit-link">Edit this page</a>
</div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<div class='footer-custom'><div class='footer-inner'><span class='footer-brand'>EchoHub</span><span class='footer-sep'>&middot;</span><a href='https://github.com/HueByte/EchoHub'>GitHub</a><span class='footer-sep'>&middot;</span><a href='https://echohub.voidcube.cloud'>Website</a><span class='footer-sep'>&middot;</span><span class='footer-credit'>Built with <a href='https://dotnet.github.io/docfx'>DocFX</a></span></div></div>
</div>
</div>
</footer>
</body>
</html>
@@ -0,0 +1,365 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Class UpdateBackupService | EchoHub Documentation </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Class UpdateBackupService | EchoHub Documentation ">
<meta name="description" content="Manages pre-update backups and rollback restoration for the auto-updater. Backup location: ~/.echohub/update-backup/">
<link rel="icon" href="../../images/hue_icon.svg">
<link rel="stylesheet" href="../../public/docfx.min.css">
<link rel="stylesheet" href="../../public/main.css">
<meta name="docfx:navrel" content="../../toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../../">
<meta name="docfx:docurl" content="https://github.com/HueByte/EchoHub/new/master/apiSpec/new?filename=EchoHub_Client_Services_UpdateBackupService.md&amp;value=---%0Auid%3A%20EchoHub.Client.Services.UpdateBackupService%0Asummary%3A%20&#39;*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax&#39;%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="ManagedReference">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../../index.html">
<img id="logo" class="svg" src="../../images/hue_icon.svg" alt="EchoHub">
EchoHub
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="EchoHub.Client.Services.UpdateBackupService">
<h1 id="EchoHub_Client_Services_UpdateBackupService" data-uid="EchoHub.Client.Services.UpdateBackupService" class="text-break">
Class UpdateBackupService <a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/UpdateBackupService.cs"><i class="bi bi-code-slash"></i></a>
</h1>
<div class="facts text-secondary">
<dl><dt>Namespace</dt><dd><a class="xref" href="EchoHub.html">EchoHub</a>.<a class="xref" href="EchoHub.Client.html">Client</a>.<a class="xref" href="EchoHub.Client.Services.html">Services</a></dd></dl>
<dl><dt>Assembly</dt><dd>EchoHub.Client.dll</dd></dl>
</div>
<div class="markdown summary"><p>Manages pre-update backups and rollback restoration for the auto-updater.
Backup location: ~/.echohub/update-backup/</p>
</div>
<div class="markdown conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static class UpdateBackupService</code></pre>
</div>
<dl class="typelist inheritance">
<dt>Inheritance</dt>
<dd>
<div><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object">object</a></div>
<div><span class="xref">UpdateBackupService</span></div>
</dd>
</dl>
<dl class="typelist inheritedMembers">
<dt>Inherited Members</dt>
<dd>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.gettype">object.GetType()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.memberwiseclone">object.MemberwiseClone()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.tostring">object.ToString()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object)">object.Equals(object)</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object-system-object)">object.Equals(object, object)</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.referenceequals">object.ReferenceEquals(object, object)</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.gethashcode">object.GetHashCode()</a>
</div>
</dd></dl>
<h2 class="section" id="properties">Properties
</h2>
<a id="EchoHub_Client_Services_UpdateBackupService_IsPostUpdate_" data-uid="EchoHub.Client.Services.UpdateBackupService.IsPostUpdate*"></a>
<h3 id="EchoHub_Client_Services_UpdateBackupService_IsPostUpdate" data-uid="EchoHub.Client.Services.UpdateBackupService.IsPostUpdate">
IsPostUpdate
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/UpdateBackupService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>True if a backup exists from a recent update (set at startup).</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static bool IsPostUpdate { get; set; }</code></pre>
</div>
<h4 class="section">Property Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.boolean">bool</a></dt>
<dd></dd>
</dl>
<h2 class="section" id="methods">Methods
</h2>
<a id="EchoHub_Client_Services_UpdateBackupService_BackupExists_" data-uid="EchoHub.Client.Services.UpdateBackupService.BackupExists*"></a>
<h3 id="EchoHub_Client_Services_UpdateBackupService_BackupExists" data-uid="EchoHub.Client.Services.UpdateBackupService.BackupExists">
BackupExists()
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/UpdateBackupService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>Returns true if a valid backup exists (both ZIP and metadata file present).</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static bool BackupExists()</code></pre>
</div>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.boolean">bool</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Client_Services_UpdateBackupService_CreateBackup_" data-uid="EchoHub.Client.Services.UpdateBackupService.CreateBackup*"></a>
<h3 id="EchoHub_Client_Services_UpdateBackupService_CreateBackup" data-uid="EchoHub.Client.Services.UpdateBackupService.CreateBackup">
CreateBackup()
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/UpdateBackupService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>Creates a ZIP backup of the current app directory before an update.
Deletes any previous backup first. Uses fastest compression for speed.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static void CreateBackup()</code></pre>
</div>
<a id="EchoHub_Client_Services_UpdateBackupService_DeleteBackup_" data-uid="EchoHub.Client.Services.UpdateBackupService.DeleteBackup*"></a>
<h3 id="EchoHub_Client_Services_UpdateBackupService_DeleteBackup" data-uid="EchoHub.Client.Services.UpdateBackupService.DeleteBackup">
DeleteBackup()
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/UpdateBackupService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>Deletes the backup directory and all contents.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static void DeleteBackup()</code></pre>
</div>
<a id="EchoHub_Client_Services_UpdateBackupService_GetBackupInfo_" data-uid="EchoHub.Client.Services.UpdateBackupService.GetBackupInfo*"></a>
<h3 id="EchoHub_Client_Services_UpdateBackupService_GetBackupInfo" data-uid="EchoHub.Client.Services.UpdateBackupService.GetBackupInfo">
GetBackupInfo()
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/UpdateBackupService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>Reads backup metadata. Returns null if no backup exists or metadata is unreadable.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static BackupInfo? GetBackupInfo()</code></pre>
</div>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="EchoHub.Client.Services.BackupInfo.html">BackupInfo</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Client_Services_UpdateBackupService_RestoreBackup_" data-uid="EchoHub.Client.Services.UpdateBackupService.RestoreBackup*"></a>
<h3 id="EchoHub_Client_Services_UpdateBackupService_RestoreBackup" data-uid="EchoHub.Client.Services.UpdateBackupService.RestoreBackup">
RestoreBackup()
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/UpdateBackupService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>Restores the backup ZIP to the app directory, then restarts the process.
This method does not return — it calls Environment.Exit(0).</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static void RestoreBackup()</code></pre>
</div>
</article>
<div class="contribution d-print-none">
<a href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/UpdateBackupService.cs" class="edit-link">Edit this page</a>
</div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<div class='footer-custom'><div class='footer-inner'><span class='footer-brand'>EchoHub</span><span class='footer-sep'>&middot;</span><a href='https://github.com/HueByte/EchoHub'>GitHub</a><span class='footer-sep'>&middot;</span><a href='https://echohub.voidcube.cloud'>Website</a><span class='footer-sep'>&middot;</span><span class='footer-credit'>Built with <a href='https://dotnet.github.io/docfx'>DocFX</a></span></div></div>
</div>
</div>
</footer>
</body>
</html>
@@ -225,6 +225,37 @@ Class UpdateChecker <a class="header-action link-secondary" title="View source"
</h2>
<a id="EchoHub_Client_Services_UpdateChecker_CheckNowAsync_" data-uid="EchoHub.Client.Services.UpdateChecker.CheckNowAsync*"></a>
<h3 id="EchoHub_Client_Services_UpdateChecker_CheckNowAsync" data-uid="EchoHub.Client.Services.UpdateChecker.CheckNowAsync">
CheckNowAsync()
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/Services/UpdateChecker.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public Task CheckNowAsync()</code></pre>
</div>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><span class="xref">Task</span></dt>
<dd></dd>
</dl>
<a id="EchoHub_Client_Services_UpdateChecker_Dispose_" data-uid="EchoHub.Client.Services.UpdateChecker.Dispose*"></a>
<h3 id="EchoHub_Client_Services_UpdateChecker_Dispose" data-uid="EchoHub.Client.Services.UpdateChecker.Dispose">
+16
View File
@@ -108,6 +108,10 @@ Runs async work on a background thread and routes exceptions to the UI.</p>
<dt><a class="xref" href="EchoHub.Client.Services.AudioPlaybackService.html">AudioPlaybackService</a></dt>
<dd></dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="EchoHub.Client.Services.BackupInfo.html">BackupInfo</a></dt>
<dd></dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="EchoHub.Client.Services.ClientEncryptionService.html">ClientEncryptionService</a></dt>
<dd><p>Client-side encryption service. Uses the same AES-256-GCM format as the server
@@ -122,6 +126,18 @@ so messages are encrypted end-to-end between client and server.</p>
<dt><a class="xref" href="EchoHub.Client.Services.NotificationSoundService.html">NotificationSoundService</a></dt>
<dd></dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="EchoHub.Client.Services.PathSetup.html">PathSetup</a></dt>
<dd><p>Ensures the application's directory is on the system PATH so users
can run 'echohub' from any terminal session.</p>
</dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="EchoHub.Client.Services.UpdateBackupService.html">UpdateBackupService</a></dt>
<dd><p>Manages pre-update backups and rollback restoration for the auto-updater.
Backup location: ~/.echohub/update-backup/</p>
</dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="EchoHub.Client.Services.UpdateChecker.html">UpdateChecker</a></dt>
<dd></dd>
@@ -184,6 +184,36 @@ Class ChatColors <a class="header-action link-secondary" title="View source" hr
<h3 id="EchoHub_Client_UI_Chat_ChatColors_ChannelRefAttr" data-uid="EchoHub.Client.UI.Chat.ChatColors.ChannelRefAttr">
ChannelRefAttr
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/UI/Chat/ChatColors.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static readonly Attribute ChannelRefAttr</code></pre>
</div>
<h4 class="section">Field Value</h4>
<dl class="parameters">
<dt><span class="xref">Attribute</span></dt>
<dd></dd>
</dl>
<h3 id="EchoHub_Client_UI_Chat_ChatColors_EmbedBorderAttr" data-uid="EchoHub.Client.UI.Chat.ChatColors.EmbedBorderAttr">
EmbedBorderAttr
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/UI/Chat/ChatColors.cs"><i class="bi bi-code-slash"></i></a>
@@ -464,8 +494,8 @@ Class ChatColors <a class="header-action link-secondary" title="View source" hr
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/UI/Chat/ChatColors.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>Split text around @mentions, giving each @word the MentionTextAttr accent color.
Non-mention text uses the provided default color.</p>
<div class="markdown level1 summary"><p>Split text around @mentions and #channels, giving each the appropriate accent color.
Non-special text uses the provided default color.</p>
</div>
<div class="markdown level1 conceptual"></div>
@@ -278,6 +278,38 @@ Class ChatLine <a class="header-action link-secondary" title="View source" href
<a id="EchoHub_Client_UI_Chat_ChatLine_ContinuationIndent_" data-uid="EchoHub.Client.UI.Chat.ChatLine.ContinuationIndent*"></a>
<h3 id="EchoHub_Client_UI_Chat_ChatLine_ContinuationIndent" data-uid="EchoHub.Client.UI.Chat.ChatLine.ContinuationIndent">
ContinuationIndent
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/UI/Chat/ChatLine.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>Number of spaces to prepend on continuation lines when this line is word-wrapped.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public int ContinuationIndent { get; set; }</code></pre>
</div>
<h4 class="section">Property Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.int32">int</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Client_UI_Chat_ChatLine_IsMention_" data-uid="EchoHub.Client.UI.Chat.ChatLine.IsMention*"></a>
<h3 id="EchoHub_Client_UI_Chat_ChatLine_IsMention" data-uid="EchoHub.Client.UI.Chat.ChatLine.IsMention">
@@ -371,6 +403,37 @@ Class ChatLine <a class="header-action link-secondary" title="View source" href
<a id="EchoHub_Client_UI_Chat_ChatLine_SenderUsername_" data-uid="EchoHub.Client.UI.Chat.ChatLine.SenderUsername*"></a>
<h3 id="EchoHub_Client_UI_Chat_ChatLine_SenderUsername" data-uid="EchoHub.Client.UI.Chat.ChatLine.SenderUsername">
SenderUsername
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/UI/Chat/ChatLine.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public string? SenderUsername { get; set; }</code></pre>
</div>
<h4 class="section">Property Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Client_UI_Chat_ChatLine_TextLength_" data-uid="EchoHub.Client.UI.Chat.ChatLine.TextLength*"></a>
<h3 id="EchoHub_Client_UI_Chat_ChatLine_TextLength" data-uid="EchoHub.Client.UI.Chat.ChatLine.TextLength">
@@ -313,6 +313,42 @@ Class UserListSource <a class="header-action link-secondary" title="View source
<a id="EchoHub_Client_UI_ListSources_UserListSource_GetUsername_" data-uid="EchoHub.Client.UI.ListSources.UserListSource.GetUsername*"></a>
<h3 id="EchoHub_Client_UI_ListSources_UserListSource_GetUsername_System_Int32_" data-uid="EchoHub.Client.UI.ListSources.UserListSource.GetUsername(System.Int32)">
GetUsername(int)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/UI/ListSources/UserListSource.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public string? GetUsername(int index)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>index</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.int32">int</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Client_UI_ListSources_UserListSource_IsMarked_" data-uid="EchoHub.Client.UI.ListSources.UserListSource.IsMarked*"></a>
<h3 id="EchoHub_Client_UI_ListSources_UserListSource_IsMarked_System_Int32_" data-uid="EchoHub.Client.UI.ListSources.UserListSource.IsMarked(System.Int32)">
@@ -458,8 +494,8 @@ Class UserListSource <a class="header-action link-secondary" title="View source
<a id="EchoHub_Client_UI_ListSources_UserListSource_Update_" data-uid="EchoHub.Client.UI.ListSources.UserListSource.Update*"></a>
<h3 id="EchoHub_Client_UI_ListSources_UserListSource_Update_System_Collections_Generic_List_System_ValueTuple_System_String_System_Nullable_Terminal_Gui_Drawing_Attribute____" data-uid="EchoHub.Client.UI.ListSources.UserListSource.Update(System.Collections.Generic.List{System.ValueTuple{System.String,System.Nullable{Terminal.Gui.Drawing.Attribute}}})">
Update(List&lt;(string Text, Attribute? NameColor)&gt;)
<h3 id="EchoHub_Client_UI_ListSources_UserListSource_Update_System_Collections_Generic_List_System_ValueTuple_System_String_System_Nullable_Terminal_Gui_Drawing_Attribute__System_String___" data-uid="EchoHub.Client.UI.ListSources.UserListSource.Update(System.Collections.Generic.List{System.ValueTuple{System.String,System.Nullable{Terminal.Gui.Drawing.Attribute},System.String}})">
Update(List&lt;(string Text, Attribute? NameColor, string Username)&gt;)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/UI/ListSources/UserListSource.cs"><i class="bi bi-code-slash"></i></a>
</h3>
@@ -467,12 +503,12 @@ Class UserListSource <a class="header-action link-secondary" title="View source
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public void Update(List&lt;(string Text, Attribute? NameColor)&gt; users)</code></pre>
<pre><code class="lang-csharp hljs">public void Update(List&lt;(string Text, Attribute? NameColor, string Username)&gt; users)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>users</code> <span class="xref">List</span>&lt;(<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.valuetuple-system.string,system.nullable-terminal.gui.drawing.attribute--.text">Text</a>, <span class="xref">Attribute</span>? <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.valuetuple-system.string,system.nullable-terminal.gui.drawing.attribute--.namecolor">NameColor</a>)&gt;</dt>
<dt><code>users</code> <span class="xref">List</span>&lt;(<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.valuetuple-system.string,system.nullable-terminal.gui.drawing.attribute-,system.string-.text">Text</a>, <span class="xref">Attribute</span>? <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.valuetuple-system.string,system.nullable-terminal.gui.drawing.attribute-,system.string-.namecolor">NameColor</a>, <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.valuetuple-system.string,system.nullable-terminal.gui.drawing.attribute-,system.string-.username">Username</a>)&gt;</dt>
<dd></dd>
</dl>
@@ -1367,6 +1367,37 @@ Call after theme changes to refresh colors.</p>
<h3 id="EchoHub_Client_UI_MainWindow_OnChannelJoinRequested" data-uid="EchoHub.Client.UI.MainWindow.OnChannelJoinRequested">
OnChannelJoinRequested
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/UI/MainWindow.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>Fired when the user activates a #channel reference in a message. Parameter is the channel name.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public event Action&lt;string&gt;? OnChannelJoinRequested</code></pre>
</div>
<h4 class="section">Event Type</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.action-1">Action</a>&lt;<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a>&gt;</dt>
<dd></dd>
</dl>
<h3 id="EchoHub_Client_UI_MainWindow_OnChannelSelected" data-uid="EchoHub.Client.UI.MainWindow.OnChannelSelected">
OnChannelSelected
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/UI/MainWindow.cs"><i class="bi bi-code-slash"></i></a>
@@ -1398,6 +1429,37 @@ Call after theme changes to refresh colors.</p>
<h3 id="EchoHub_Client_UI_MainWindow_OnCheckForUpdatesRequested" data-uid="EchoHub.Client.UI.MainWindow.OnCheckForUpdatesRequested">
OnCheckForUpdatesRequested
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/UI/MainWindow.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>Fired when the user requests to check for updates.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public event Action? OnCheckForUpdatesRequested</code></pre>
</div>
<h4 class="section">Event Type</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.action">Action</a></dt>
<dd></dd>
</dl>
<h3 id="EchoHub_Client_UI_MainWindow_OnConnectRequested" data-uid="EchoHub.Client.UI.MainWindow.OnConnectRequested">
OnConnectRequested
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/UI/MainWindow.cs"><i class="bi bi-code-slash"></i></a>
@@ -1646,6 +1708,37 @@ Call after theme changes to refresh colors.</p>
<h3 id="EchoHub_Client_UI_MainWindow_OnRollbackRequested" data-uid="EchoHub.Client.UI.MainWindow.OnRollbackRequested">
OnRollbackRequested
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/UI/MainWindow.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>Fired when the user requests to rollback to the previous version.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public event Action? OnRollbackRequested</code></pre>
</div>
<h4 class="section">Event Type</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.action">Action</a></dt>
<dd></dd>
</dl>
<h3 id="EchoHub_Client_UI_MainWindow_OnSavedServersRequested" data-uid="EchoHub.Client.UI.MainWindow.OnSavedServersRequested">
OnSavedServersRequested
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/UI/MainWindow.cs"><i class="bi bi-code-slash"></i></a>
@@ -1739,6 +1832,37 @@ Call after theme changes to refresh colors.</p>
<h3 id="EchoHub_Client_UI_MainWindow_OnUserProfileRequested" data-uid="EchoHub.Client.UI.MainWindow.OnUserProfileRequested">
OnUserProfileRequested
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Client/UI/MainWindow.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"><p>Fired when the user activates a username (in userlist or message). Parameter is the username.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public event Action&lt;string&gt;? OnUserProfileRequested</code></pre>
</div>
<h4 class="section">Event Type</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.action-1">Action</a>&lt;<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a>&gt;</dt>
<dd></dd>
</dl>
</article>
<div class="contribution d-print-none">
@@ -386,8 +386,8 @@ Interface IChatBroadcaster <a class="header-action link-secondary" title="View
<a id="EchoHub_Core_Contracts_IChatBroadcaster_SendUserJoinedAsync_" data-uid="EchoHub.Core.Contracts.IChatBroadcaster.SendUserJoinedAsync*"></a>
<h3 id="EchoHub_Core_Contracts_IChatBroadcaster_SendUserJoinedAsync_System_String_System_String_System_String_" data-uid="EchoHub.Core.Contracts.IChatBroadcaster.SendUserJoinedAsync(System.String,System.String,System.String)">
SendUserJoinedAsync(string, string, string?)
<h3 id="EchoHub_Core_Contracts_IChatBroadcaster_SendUserJoinedAsync_System_String_System_String_EchoHub_Core_DTOs_UserPresenceDto_System_String_" data-uid="EchoHub.Core.Contracts.IChatBroadcaster.SendUserJoinedAsync(System.String,System.String,EchoHub.Core.DTOs.UserPresenceDto,System.String)">
SendUserJoinedAsync(string, string, UserPresenceDto?, string?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/Contracts/IChatBroadcaster.cs"><i class="bi bi-code-slash"></i></a>
</h3>
@@ -395,7 +395,7 @@ Interface IChatBroadcaster <a class="header-action link-secondary" title="View
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">Task SendUserJoinedAsync(string channelName, string username, string? excludeConnectionId = null)</code></pre>
<pre><code class="lang-csharp hljs">Task SendUserJoinedAsync(string channelName, string username, UserPresenceDto? presence, string? excludeConnectionId = null)</code></pre>
</div>
<h4 class="section">Parameters</h4>
@@ -404,6 +404,8 @@ Interface IChatBroadcaster <a class="header-action link-secondary" title="View
<dd></dd>
<dt><code>username</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dt><code>presence</code> <a class="xref" href="EchoHub.Core.DTOs.UserPresenceDto.html">UserPresenceDto</a></dt>
<dd></dd>
<dt><code>excludeConnectionId</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
@@ -120,44 +120,6 @@ Interface IChatService <a class="header-action link-secondary" title="View sour
</h2>
<a id="EchoHub_Core_Contracts_IChatService_AuthenticateUserAsync_" data-uid="EchoHub.Core.Contracts.IChatService.AuthenticateUserAsync*"></a>
<h3 id="EchoHub_Core_Contracts_IChatService_AuthenticateUserAsync_System_String_System_String_" data-uid="EchoHub.Core.Contracts.IChatService.AuthenticateUserAsync(System.String,System.String)">
AuthenticateUserAsync(string, string)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/Contracts/IChatService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">Task&lt;(Guid UserId, string Username)?&gt; AuthenticateUserAsync(string username, string password)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>username</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dt><code>password</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><span class="xref">Task</span>&lt;(<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.guid">Guid</a> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.valuetuple-system.guid,system.string-.userid">UserId</a>, <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.valuetuple-system.guid,system.string-.username">Username</a>)?&gt;</dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_Contracts_IChatService_BroadcastChannelUpdatedAsync_" data-uid="EchoHub.Core.Contracts.IChatService.BroadcastChannelUpdatedAsync*"></a>
<h3 id="EchoHub_Core_Contracts_IChatService_BroadcastChannelUpdatedAsync_EchoHub_Core_DTOs_ChannelDto_System_String_" data-uid="EchoHub.Core.Contracts.IChatService.BroadcastChannelUpdatedAsync(EchoHub.Core.DTOs.ChannelDto,System.String)">
@@ -344,42 +306,6 @@ Interface IChatService <a class="header-action link-secondary" title="View sour
<a id="EchoHub_Core_Contracts_IChatService_GetUserProfileAsync_" data-uid="EchoHub.Core.Contracts.IChatService.GetUserProfileAsync*"></a>
<h3 id="EchoHub_Core_Contracts_IChatService_GetUserProfileAsync_System_String_" data-uid="EchoHub.Core.Contracts.IChatService.GetUserProfileAsync(System.String)">
GetUserProfileAsync(string)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/Contracts/IChatService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">Task&lt;UserProfileDto?&gt; GetUserProfileAsync(string username)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>username</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><span class="xref">Task</span>&lt;<a class="xref" href="EchoHub.Core.DTOs.UserProfileDto.html">UserProfileDto</a>&gt;</dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_Contracts_IChatService_JoinChannelAsync_" data-uid="EchoHub.Core.Contracts.IChatService.JoinChannelAsync*"></a>
<h3 id="EchoHub_Core_Contracts_IChatService_JoinChannelAsync_System_String_System_Guid_System_String_System_String_" data-uid="EchoHub.Core.Contracts.IChatService.JoinChannelAsync(System.String,System.Guid,System.String,System.String)">
@@ -379,8 +379,8 @@ Interface IEchoHubClient <a class="header-action link-secondary" title="View so
<a id="EchoHub_Core_Contracts_IEchoHubClient_UserJoined_" data-uid="EchoHub.Core.Contracts.IEchoHubClient.UserJoined*"></a>
<h3 id="EchoHub_Core_Contracts_IEchoHubClient_UserJoined_System_String_System_String_" data-uid="EchoHub.Core.Contracts.IEchoHubClient.UserJoined(System.String,System.String)">
UserJoined(string, string)
<h3 id="EchoHub_Core_Contracts_IEchoHubClient_UserJoined_System_String_System_String_EchoHub_Core_DTOs_UserPresenceDto_" data-uid="EchoHub.Core.Contracts.IEchoHubClient.UserJoined(System.String,System.String,EchoHub.Core.DTOs.UserPresenceDto)">
UserJoined(string, string, UserPresenceDto?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/Contracts/IEchoHubClient.cs"><i class="bi bi-code-slash"></i></a>
</h3>
@@ -388,7 +388,7 @@ Interface IEchoHubClient <a class="header-action link-secondary" title="View so
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">Task UserJoined(string channelName, string username)</code></pre>
<pre><code class="lang-csharp hljs">Task UserJoined(string channelName, string username, UserPresenceDto? presence)</code></pre>
</div>
<h4 class="section">Parameters</h4>
@@ -397,6 +397,8 @@ Interface IEchoHubClient <a class="header-action link-secondary" title="View so
<dd></dd>
<dt><code>username</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dt><code>presence</code> <a class="xref" href="EchoHub.Core.DTOs.UserPresenceDto.html">UserPresenceDto</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
@@ -0,0 +1,378 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Interface IUserService | EchoHub Documentation </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Interface IUserService | EchoHub Documentation ">
<link rel="icon" href="../../images/hue_icon.svg">
<link rel="stylesheet" href="../../public/docfx.min.css">
<link rel="stylesheet" href="../../public/main.css">
<meta name="docfx:navrel" content="../../toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../../">
<meta name="docfx:docurl" content="https://github.com/HueByte/EchoHub/new/master/apiSpec/new?filename=EchoHub_Core_Contracts_IUserService.md&amp;value=---%0Auid%3A%20EchoHub.Core.Contracts.IUserService%0Asummary%3A%20&#39;*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax&#39;%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="ManagedReference">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../../index.html">
<img id="logo" class="svg" src="../../images/hue_icon.svg" alt="EchoHub">
EchoHub
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="EchoHub.Core.Contracts.IUserService">
<h1 id="EchoHub_Core_Contracts_IUserService" data-uid="EchoHub.Core.Contracts.IUserService" class="text-break">
Interface IUserService <a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/Contracts/IUserService.cs"><i class="bi bi-code-slash"></i></a>
</h1>
<div class="facts text-secondary">
<dl><dt>Namespace</dt><dd><a class="xref" href="EchoHub.html">EchoHub</a>.<a class="xref" href="EchoHub.Core.html">Core</a>.<a class="xref" href="EchoHub.Core.Contracts.html">Contracts</a></dd></dl>
<dl><dt>Assembly</dt><dd>EchoHub.Core.dll</dd></dl>
</div>
<div class="markdown summary"></div>
<div class="markdown conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public interface IUserService</code></pre>
</div>
<h2 class="section" id="methods">Methods
</h2>
<a id="EchoHub_Core_Contracts_IUserService_AuthenticateUserAsync_" data-uid="EchoHub.Core.Contracts.IUserService.AuthenticateUserAsync*"></a>
<h3 id="EchoHub_Core_Contracts_IUserService_AuthenticateUserAsync_System_String_System_String_" data-uid="EchoHub.Core.Contracts.IUserService.AuthenticateUserAsync(System.String,System.String)">
AuthenticateUserAsync(string, string)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/Contracts/IUserService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">Task&lt;UserOperationResult&gt; AuthenticateUserAsync(string username, string password)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>username</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dt><code>password</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><span class="xref">Task</span>&lt;<a class="xref" href="EchoHub.Core.DTOs.UserOperationResult.html">UserOperationResult</a>&gt;</dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_Contracts_IUserService_GetUserByIdAsync_" data-uid="EchoHub.Core.Contracts.IUserService.GetUserByIdAsync*"></a>
<h3 id="EchoHub_Core_Contracts_IUserService_GetUserByIdAsync_System_Guid_" data-uid="EchoHub.Core.Contracts.IUserService.GetUserByIdAsync(System.Guid)">
GetUserByIdAsync(Guid)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/Contracts/IUserService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">Task&lt;UserProfileDto?&gt; GetUserByIdAsync(Guid userId)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>userId</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.guid">Guid</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><span class="xref">Task</span>&lt;<a class="xref" href="EchoHub.Core.DTOs.UserProfileDto.html">UserProfileDto</a>&gt;</dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_Contracts_IUserService_GetUserProfileAsync_" data-uid="EchoHub.Core.Contracts.IUserService.GetUserProfileAsync*"></a>
<h3 id="EchoHub_Core_Contracts_IUserService_GetUserProfileAsync_System_String_" data-uid="EchoHub.Core.Contracts.IUserService.GetUserProfileAsync(System.String)">
GetUserProfileAsync(string)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/Contracts/IUserService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">Task&lt;UserProfileDto?&gt; GetUserProfileAsync(string username)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>username</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><span class="xref">Task</span>&lt;<a class="xref" href="EchoHub.Core.DTOs.UserProfileDto.html">UserProfileDto</a>&gt;</dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_Contracts_IUserService_RegisterUserAsync_" data-uid="EchoHub.Core.Contracts.IUserService.RegisterUserAsync*"></a>
<h3 id="EchoHub_Core_Contracts_IUserService_RegisterUserAsync_System_String_System_String_System_String_" data-uid="EchoHub.Core.Contracts.IUserService.RegisterUserAsync(System.String,System.String,System.String)">
RegisterUserAsync(string, string, string?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/Contracts/IUserService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">Task&lt;UserOperationResult&gt; RegisterUserAsync(string username, string password, string? displayName = null)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>username</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dt><code>password</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dt><code>displayName</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><span class="xref">Task</span>&lt;<a class="xref" href="EchoHub.Core.DTOs.UserOperationResult.html">UserOperationResult</a>&gt;</dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_Contracts_IUserService_SetAvatarAsync_" data-uid="EchoHub.Core.Contracts.IUserService.SetAvatarAsync*"></a>
<h3 id="EchoHub_Core_Contracts_IUserService_SetAvatarAsync_System_Guid_System_String_" data-uid="EchoHub.Core.Contracts.IUserService.SetAvatarAsync(System.Guid,System.String)">
SetAvatarAsync(Guid, string)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/Contracts/IUserService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">Task&lt;UserOperationResult&gt; SetAvatarAsync(Guid userId, string asciiArt)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>userId</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.guid">Guid</a></dt>
<dd></dd>
<dt><code>asciiArt</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><span class="xref">Task</span>&lt;<a class="xref" href="EchoHub.Core.DTOs.UserOperationResult.html">UserOperationResult</a>&gt;</dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_Contracts_IUserService_UpdateProfileAsync_" data-uid="EchoHub.Core.Contracts.IUserService.UpdateProfileAsync*"></a>
<h3 id="EchoHub_Core_Contracts_IUserService_UpdateProfileAsync_System_Guid_System_String_System_String_System_String_" data-uid="EchoHub.Core.Contracts.IUserService.UpdateProfileAsync(System.Guid,System.String,System.String,System.String)">
UpdateProfileAsync(Guid, string?, string?, string?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/Contracts/IUserService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">Task&lt;UserOperationResult&gt; UpdateProfileAsync(Guid userId, string? displayName, string? bio, string? nicknameColor)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>userId</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.guid">Guid</a></dt>
<dd></dd>
<dt><code>displayName</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dt><code>bio</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dt><code>nicknameColor</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><span class="xref">Task</span>&lt;<a class="xref" href="EchoHub.Core.DTOs.UserOperationResult.html">UserOperationResult</a>&gt;</dt>
<dd></dd>
</dl>
</article>
<div class="contribution d-print-none">
<a href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/Contracts/IUserService.cs" class="edit-link">Edit this page</a>
</div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<div class='footer-custom'><div class='footer-inner'><span class='footer-brand'>EchoHub</span><span class='footer-sep'>&middot;</span><a href='https://github.com/HueByte/EchoHub'>GitHub</a><span class='footer-sep'>&middot;</span><a href='https://echohub.voidcube.cloud'>Website</a><span class='footer-sep'>&middot;</span><span class='footer-credit'>Built with <a href='https://dotnet.github.io/docfx'>DocFX</a></span></div></div>
</div>
</div>
</footer>
</body>
</html>
+4
View File
@@ -122,6 +122,10 @@ Interfaces
<dt><a class="xref" href="EchoHub.Core.Contracts.IMessageEncryptionService.html">IMessageEncryptionService</a></dt>
<dd></dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="EchoHub.Core.Contracts.IUserService.html">IUserService</a></dt>
<dd></dd>
</dl>
</article>
+41 -6
View File
@@ -182,8 +182,8 @@ Class EmbedDto <a class="header-action link-secondary" title="View source" href
<a id="EchoHub_Core_DTOs_EmbedDto__ctor_" data-uid="EchoHub.Core.DTOs.EmbedDto.#ctor*"></a>
<h3 id="EchoHub_Core_DTOs_EmbedDto__ctor_System_String_System_String_System_String_System_String_System_String_" data-uid="EchoHub.Core.DTOs.EmbedDto.#ctor(System.String,System.String,System.String,System.String,System.String)">
EmbedDto(string?, string?, string?, string?, string)
<h3 id="EchoHub_Core_DTOs_EmbedDto__ctor_System_String_System_String_System_String_System_String_System_String_System_String_" data-uid="EchoHub.Core.DTOs.EmbedDto.#ctor(System.String,System.String,System.String,System.String,System.String,System.String)">
EmbedDto(string?, string?, string?, string?, string, string?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/ChatDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
@@ -191,7 +191,7 @@ Class EmbedDto <a class="header-action link-secondary" title="View source" href
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public EmbedDto(string? SiteName, string? Title, string? Description, string? ImageAscii, string Url)</code></pre>
<pre><code class="lang-csharp hljs">public EmbedDto(string? SiteName, string? Title, string? Description, string? ImageAscii, string Url, string? ThemeColor = null)</code></pre>
</div>
<h4 class="section">Parameters</h4>
@@ -206,6 +206,8 @@ Class EmbedDto <a class="header-action link-secondary" title="View source" href
<dd></dd>
<dt><code>Url</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dt><code>ThemeColor</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
@@ -347,6 +349,37 @@ Class EmbedDto <a class="header-action link-secondary" title="View source" href
<a id="EchoHub_Core_DTOs_EmbedDto_ThemeColor_" data-uid="EchoHub.Core.DTOs.EmbedDto.ThemeColor*"></a>
<h3 id="EchoHub_Core_DTOs_EmbedDto_ThemeColor" data-uid="EchoHub.Core.DTOs.EmbedDto.ThemeColor">
ThemeColor
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/ChatDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public string? ThemeColor { get; init; }</code></pre>
</div>
<h4 class="section">Property Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_DTOs_EmbedDto_Title_" data-uid="EchoHub.Core.DTOs.EmbedDto.Title*"></a>
<h3 id="EchoHub_Core_DTOs_EmbedDto_Title" data-uid="EchoHub.Core.DTOs.EmbedDto.Title">
@@ -415,8 +448,8 @@ Class EmbedDto <a class="header-action link-secondary" title="View source" href
<a id="EchoHub_Core_DTOs_EmbedDto_Deconstruct_" data-uid="EchoHub.Core.DTOs.EmbedDto.Deconstruct*"></a>
<h3 id="EchoHub_Core_DTOs_EmbedDto_Deconstruct_System_String__System_String__System_String__System_String__System_String__" data-uid="EchoHub.Core.DTOs.EmbedDto.Deconstruct(System.String@,System.String@,System.String@,System.String@,System.String@)">
Deconstruct(out string?, out string?, out string?, out string?, out string)
<h3 id="EchoHub_Core_DTOs_EmbedDto_Deconstruct_System_String__System_String__System_String__System_String__System_String__System_String__" data-uid="EchoHub.Core.DTOs.EmbedDto.Deconstruct(System.String@,System.String@,System.String@,System.String@,System.String@,System.String@)">
Deconstruct(out string?, out string?, out string?, out string?, out string, out string?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/ChatDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
@@ -424,7 +457,7 @@ Class EmbedDto <a class="header-action link-secondary" title="View source" href
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public void Deconstruct(out string? SiteName, out string? Title, out string? Description, out string? ImageAscii, out string Url)</code></pre>
<pre><code class="lang-csharp hljs">public void Deconstruct(out string? SiteName, out string? Title, out string? Description, out string? ImageAscii, out string Url, out string? ThemeColor)</code></pre>
</div>
<h4 class="section">Parameters</h4>
@@ -439,6 +472,8 @@ Class EmbedDto <a class="header-action link-secondary" title="View source" href
<dd></dd>
<dt><code>Url</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dt><code>ThemeColor</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
@@ -0,0 +1,660 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Class JoinChannelResult | EchoHub Documentation </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Class JoinChannelResult | EchoHub Documentation ">
<link rel="icon" href="../../images/hue_icon.svg">
<link rel="stylesheet" href="../../public/docfx.min.css">
<link rel="stylesheet" href="../../public/main.css">
<meta name="docfx:navrel" content="../../toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../../">
<meta name="docfx:docurl" content="https://github.com/HueByte/EchoHub/new/master/apiSpec/new?filename=EchoHub_Core_DTOs_JoinChannelResult.md&amp;value=---%0Auid%3A%20EchoHub.Core.DTOs.JoinChannelResult%0Asummary%3A%20&#39;*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax&#39;%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="ManagedReference">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../../index.html">
<img id="logo" class="svg" src="../../images/hue_icon.svg" alt="EchoHub">
EchoHub
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="EchoHub.Core.DTOs.JoinChannelResult">
<h1 id="EchoHub_Core_DTOs_JoinChannelResult" data-uid="EchoHub.Core.DTOs.JoinChannelResult" class="text-break">
Class JoinChannelResult <a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/ChatDtos.cs"><i class="bi bi-code-slash"></i></a>
</h1>
<div class="facts text-secondary">
<dl><dt>Namespace</dt><dd><a class="xref" href="EchoHub.html">EchoHub</a>.<a class="xref" href="EchoHub.Core.html">Core</a>.<a class="xref" href="EchoHub.Core.DTOs.html">DTOs</a></dd></dl>
<dl><dt>Assembly</dt><dd>EchoHub.Core.dll</dd></dl>
</div>
<div class="markdown summary"></div>
<div class="markdown conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public record JoinChannelResult : IEquatable&lt;JoinChannelResult&gt;</code></pre>
</div>
<dl class="typelist inheritance">
<dt>Inheritance</dt>
<dd>
<div><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object">object</a></div>
<div><span class="xref">JoinChannelResult</span></div>
</dd>
</dl>
<dl class="typelist implements">
<dt>Implements</dt>
<dd>
<div><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.iequatable-1">IEquatable</a>&lt;<a class="xref" href="EchoHub.Core.DTOs.JoinChannelResult.html">JoinChannelResult</a>&gt;</div>
</dd>
</dl>
<dl class="typelist inheritedMembers">
<dt>Inherited Members</dt>
<dd>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.gettype">object.GetType()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.memberwiseclone">object.MemberwiseClone()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object-system-object)">object.Equals(object, object)</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.referenceequals">object.ReferenceEquals(object, object)</a>
</div>
</dd></dl>
<h2 class="section" id="constructors">Constructors
</h2>
<a id="EchoHub_Core_DTOs_JoinChannelResult__ctor_" data-uid="EchoHub.Core.DTOs.JoinChannelResult.#ctor*"></a>
<h3 id="EchoHub_Core_DTOs_JoinChannelResult__ctor_EchoHub_Core_DTOs_JoinChannelResult_" data-uid="EchoHub.Core.DTOs.JoinChannelResult.#ctor(EchoHub.Core.DTOs.JoinChannelResult)">
JoinChannelResult(JoinChannelResult)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/ChatDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">protected JoinChannelResult(JoinChannelResult original)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>original</code> <a class="xref" href="EchoHub.Core.DTOs.JoinChannelResult.html">JoinChannelResult</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_DTOs_JoinChannelResult__ctor_" data-uid="EchoHub.Core.DTOs.JoinChannelResult.#ctor*"></a>
<h3 id="EchoHub_Core_DTOs_JoinChannelResult__ctor_System_Boolean_System_Collections_Generic_List_EchoHub_Core_DTOs_MessageDto__System_String_" data-uid="EchoHub.Core.DTOs.JoinChannelResult.#ctor(System.Boolean,System.Collections.Generic.List{EchoHub.Core.DTOs.MessageDto},System.String)">
JoinChannelResult(bool, List&lt;MessageDto&gt;, string?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/ChatDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public JoinChannelResult(bool Success, List&lt;MessageDto&gt; History, string? Error = null)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>Success</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.boolean">bool</a></dt>
<dd></dd>
<dt><code>History</code> <span class="xref">List</span>&lt;<a class="xref" href="EchoHub.Core.DTOs.MessageDto.html">MessageDto</a>&gt;</dt>
<dd></dd>
<dt><code>Error</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h2 class="section" id="properties">Properties
</h2>
<a id="EchoHub_Core_DTOs_JoinChannelResult_EqualityContract_" data-uid="EchoHub.Core.DTOs.JoinChannelResult.EqualityContract*"></a>
<h3 id="EchoHub_Core_DTOs_JoinChannelResult_EqualityContract" data-uid="EchoHub.Core.DTOs.JoinChannelResult.EqualityContract">
EqualityContract
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/ChatDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">protected virtual Type EqualityContract { get; }</code></pre>
</div>
<h4 class="section">Property Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.type">Type</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_DTOs_JoinChannelResult_Error_" data-uid="EchoHub.Core.DTOs.JoinChannelResult.Error*"></a>
<h3 id="EchoHub_Core_DTOs_JoinChannelResult_Error" data-uid="EchoHub.Core.DTOs.JoinChannelResult.Error">
Error
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/ChatDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public string? Error { get; init; }</code></pre>
</div>
<h4 class="section">Property Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_DTOs_JoinChannelResult_History_" data-uid="EchoHub.Core.DTOs.JoinChannelResult.History*"></a>
<h3 id="EchoHub_Core_DTOs_JoinChannelResult_History" data-uid="EchoHub.Core.DTOs.JoinChannelResult.History">
History
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/ChatDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public List&lt;MessageDto&gt; History { get; init; }</code></pre>
</div>
<h4 class="section">Property Value</h4>
<dl class="parameters">
<dt><span class="xref">List</span>&lt;<a class="xref" href="EchoHub.Core.DTOs.MessageDto.html">MessageDto</a>&gt;</dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_DTOs_JoinChannelResult_Success_" data-uid="EchoHub.Core.DTOs.JoinChannelResult.Success*"></a>
<h3 id="EchoHub_Core_DTOs_JoinChannelResult_Success" data-uid="EchoHub.Core.DTOs.JoinChannelResult.Success">
Success
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/ChatDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public bool Success { get; init; }</code></pre>
</div>
<h4 class="section">Property Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.boolean">bool</a></dt>
<dd></dd>
</dl>
<h2 class="section" id="methods">Methods
</h2>
<a id="EchoHub_Core_DTOs_JoinChannelResult_Deconstruct_" data-uid="EchoHub.Core.DTOs.JoinChannelResult.Deconstruct*"></a>
<h3 id="EchoHub_Core_DTOs_JoinChannelResult_Deconstruct_System_Boolean__System_Collections_Generic_List_EchoHub_Core_DTOs_MessageDto___System_String__" data-uid="EchoHub.Core.DTOs.JoinChannelResult.Deconstruct(System.Boolean@,System.Collections.Generic.List{EchoHub.Core.DTOs.MessageDto}@,System.String@)">
Deconstruct(out bool, out List&lt;MessageDto&gt;, out string?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/ChatDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public void Deconstruct(out bool Success, out List&lt;MessageDto&gt; History, out string? Error)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>Success</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.boolean">bool</a></dt>
<dd></dd>
<dt><code>History</code> <span class="xref">List</span>&lt;<a class="xref" href="EchoHub.Core.DTOs.MessageDto.html">MessageDto</a>&gt;</dt>
<dd></dd>
<dt><code>Error</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_DTOs_JoinChannelResult_Equals_" data-uid="EchoHub.Core.DTOs.JoinChannelResult.Equals*"></a>
<h3 id="EchoHub_Core_DTOs_JoinChannelResult_Equals_EchoHub_Core_DTOs_JoinChannelResult_" data-uid="EchoHub.Core.DTOs.JoinChannelResult.Equals(EchoHub.Core.DTOs.JoinChannelResult)">
Equals(JoinChannelResult?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/ChatDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public virtual bool Equals(JoinChannelResult? other)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>other</code> <a class="xref" href="EchoHub.Core.DTOs.JoinChannelResult.html">JoinChannelResult</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.boolean">bool</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_DTOs_JoinChannelResult_Equals_" data-uid="EchoHub.Core.DTOs.JoinChannelResult.Equals*"></a>
<h3 id="EchoHub_Core_DTOs_JoinChannelResult_Equals_System_Object_" data-uid="EchoHub.Core.DTOs.JoinChannelResult.Equals(System.Object)">
Equals(object?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/ChatDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public override bool Equals(object? obj)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>obj</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object">object</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.boolean">bool</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_DTOs_JoinChannelResult_GetHashCode_" data-uid="EchoHub.Core.DTOs.JoinChannelResult.GetHashCode*"></a>
<h3 id="EchoHub_Core_DTOs_JoinChannelResult_GetHashCode" data-uid="EchoHub.Core.DTOs.JoinChannelResult.GetHashCode">
GetHashCode()
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/ChatDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public override int GetHashCode()</code></pre>
</div>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.int32">int</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_DTOs_JoinChannelResult_PrintMembers_" data-uid="EchoHub.Core.DTOs.JoinChannelResult.PrintMembers*"></a>
<h3 id="EchoHub_Core_DTOs_JoinChannelResult_PrintMembers_System_Text_StringBuilder_" data-uid="EchoHub.Core.DTOs.JoinChannelResult.PrintMembers(System.Text.StringBuilder)">
PrintMembers(StringBuilder)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/ChatDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">protected virtual bool PrintMembers(StringBuilder builder)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>builder</code> <span class="xref">StringBuilder</span></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.boolean">bool</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_DTOs_JoinChannelResult_ToString_" data-uid="EchoHub.Core.DTOs.JoinChannelResult.ToString*"></a>
<h3 id="EchoHub_Core_DTOs_JoinChannelResult_ToString" data-uid="EchoHub.Core.DTOs.JoinChannelResult.ToString">
ToString()
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/ChatDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public override string ToString()</code></pre>
</div>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h2 class="section" id="operators">Operators
</h2>
<a id="EchoHub_Core_DTOs_JoinChannelResult_op_Equality_" data-uid="EchoHub.Core.DTOs.JoinChannelResult.op_Equality*"></a>
<h3 id="EchoHub_Core_DTOs_JoinChannelResult_op_Equality_EchoHub_Core_DTOs_JoinChannelResult_EchoHub_Core_DTOs_JoinChannelResult_" data-uid="EchoHub.Core.DTOs.JoinChannelResult.op_Equality(EchoHub.Core.DTOs.JoinChannelResult,EchoHub.Core.DTOs.JoinChannelResult)">
operator ==(JoinChannelResult?, JoinChannelResult?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/ChatDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static bool operator ==(JoinChannelResult? left, JoinChannelResult? right)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>left</code> <a class="xref" href="EchoHub.Core.DTOs.JoinChannelResult.html">JoinChannelResult</a></dt>
<dd></dd>
<dt><code>right</code> <a class="xref" href="EchoHub.Core.DTOs.JoinChannelResult.html">JoinChannelResult</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.boolean">bool</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_DTOs_JoinChannelResult_op_Inequality_" data-uid="EchoHub.Core.DTOs.JoinChannelResult.op_Inequality*"></a>
<h3 id="EchoHub_Core_DTOs_JoinChannelResult_op_Inequality_EchoHub_Core_DTOs_JoinChannelResult_EchoHub_Core_DTOs_JoinChannelResult_" data-uid="EchoHub.Core.DTOs.JoinChannelResult.op_Inequality(EchoHub.Core.DTOs.JoinChannelResult,EchoHub.Core.DTOs.JoinChannelResult)">
operator !=(JoinChannelResult?, JoinChannelResult?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/ChatDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static bool operator !=(JoinChannelResult? left, JoinChannelResult? right)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>left</code> <a class="xref" href="EchoHub.Core.DTOs.JoinChannelResult.html">JoinChannelResult</a></dt>
<dd></dd>
<dt><code>right</code> <a class="xref" href="EchoHub.Core.DTOs.JoinChannelResult.html">JoinChannelResult</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.boolean">bool</a></dt>
<dd></dd>
</dl>
</article>
<div class="contribution d-print-none">
<a href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/ChatDtos.cs" class="edit-link">Edit this page</a>
</div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<div class='footer-custom'><div class='footer-inner'><span class='footer-brand'>EchoHub</span><span class='footer-sep'>&middot;</span><a href='https://github.com/HueByte/EchoHub'>GitHub</a><span class='footer-sep'>&middot;</span><a href='https://echohub.voidcube.cloud'>Website</a><span class='footer-sep'>&middot;</span><span class='footer-credit'>Built with <a href='https://dotnet.github.io/docfx'>DocFX</a></span></div></div>
</div>
</div>
</footer>
</body>
</html>
+162
View File
@@ -0,0 +1,162 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Enum UserError | EchoHub Documentation </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Enum UserError | EchoHub Documentation ">
<link rel="icon" href="../../images/hue_icon.svg">
<link rel="stylesheet" href="../../public/docfx.min.css">
<link rel="stylesheet" href="../../public/main.css">
<meta name="docfx:navrel" content="../../toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../../">
<meta name="docfx:docurl" content="https://github.com/HueByte/EchoHub/new/master/apiSpec/new?filename=EchoHub_Core_DTOs_UserError.md&amp;value=---%0Auid%3A%20EchoHub.Core.DTOs.UserError%0Asummary%3A%20&#39;*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax&#39;%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="ManagedReference">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../../index.html">
<img id="logo" class="svg" src="../../images/hue_icon.svg" alt="EchoHub">
EchoHub
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="EchoHub.Core.DTOs.UserError">
<h1 id="EchoHub_Core_DTOs_UserError" data-uid="EchoHub.Core.DTOs.UserError" class="text-break">
Enum UserError <a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/CommonDtos.cs"><i class="bi bi-code-slash"></i></a>
</h1>
<div class="facts text-secondary">
<dl><dt>Namespace</dt><dd><a class="xref" href="EchoHub.html">EchoHub</a>.<a class="xref" href="EchoHub.Core.html">Core</a>.<a class="xref" href="EchoHub.Core.DTOs.html">DTOs</a></dd></dl>
<dl><dt>Assembly</dt><dd>EchoHub.Core.dll</dd></dl>
</div>
<div class="markdown summary"></div>
<div class="markdown conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public enum UserError</code></pre>
</div>
<h2 id="fields">Fields
</h2>
<dl class="parameters">
<dt id="EchoHub_Core_DTOs_UserError_AlreadyExists"><code>AlreadyExists = 1</code></dt>
<dd></dd>
<dt id="EchoHub_Core_DTOs_UserError_Banned"><code>Banned = 4</code></dt>
<dd></dd>
<dt id="EchoHub_Core_DTOs_UserError_InvalidCredentials"><code>InvalidCredentials = 3</code></dt>
<dd></dd>
<dt id="EchoHub_Core_DTOs_UserError_NotFound"><code>NotFound = 2</code></dt>
<dd></dd>
<dt id="EchoHub_Core_DTOs_UserError_ValidationFailed"><code>ValidationFailed = 0</code></dt>
<dd></dd>
</dl>
</article>
<div class="contribution d-print-none">
<a href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/CommonDtos.cs" class="edit-link">Edit this page</a>
</div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<div class='footer-custom'><div class='footer-inner'><span class='footer-brand'>EchoHub</span><span class='footer-sep'>&middot;</span><a href='https://github.com/HueByte/EchoHub'>GitHub</a><span class='footer-sep'>&middot;</span><a href='https://echohub.voidcube.cloud'>Website</a><span class='footer-sep'>&middot;</span><span class='footer-credit'>Built with <a href='https://dotnet.github.io/docfx'>DocFX</a></span></div></div>
</div>
</div>
</footer>
</body>
</html>
@@ -0,0 +1,765 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Class UserOperationResult | EchoHub Documentation </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Class UserOperationResult | EchoHub Documentation ">
<link rel="icon" href="../../images/hue_icon.svg">
<link rel="stylesheet" href="../../public/docfx.min.css">
<link rel="stylesheet" href="../../public/main.css">
<meta name="docfx:navrel" content="../../toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../../">
<meta name="docfx:docurl" content="https://github.com/HueByte/EchoHub/new/master/apiSpec/new?filename=EchoHub_Core_DTOs_UserOperationResult.md&amp;value=---%0Auid%3A%20EchoHub.Core.DTOs.UserOperationResult%0Asummary%3A%20&#39;*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax&#39;%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="ManagedReference">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../../index.html">
<img id="logo" class="svg" src="../../images/hue_icon.svg" alt="EchoHub">
EchoHub
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="EchoHub.Core.DTOs.UserOperationResult">
<h1 id="EchoHub_Core_DTOs_UserOperationResult" data-uid="EchoHub.Core.DTOs.UserOperationResult" class="text-break">
Class UserOperationResult <a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/CommonDtos.cs"><i class="bi bi-code-slash"></i></a>
</h1>
<div class="facts text-secondary">
<dl><dt>Namespace</dt><dd><a class="xref" href="EchoHub.html">EchoHub</a>.<a class="xref" href="EchoHub.Core.html">Core</a>.<a class="xref" href="EchoHub.Core.DTOs.html">DTOs</a></dd></dl>
<dl><dt>Assembly</dt><dd>EchoHub.Core.dll</dd></dl>
</div>
<div class="markdown summary"></div>
<div class="markdown conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public record UserOperationResult : IEquatable&lt;UserOperationResult&gt;</code></pre>
</div>
<dl class="typelist inheritance">
<dt>Inheritance</dt>
<dd>
<div><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object">object</a></div>
<div><span class="xref">UserOperationResult</span></div>
</dd>
</dl>
<dl class="typelist implements">
<dt>Implements</dt>
<dd>
<div><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.iequatable-1">IEquatable</a>&lt;<a class="xref" href="EchoHub.Core.DTOs.UserOperationResult.html">UserOperationResult</a>&gt;</div>
</dd>
</dl>
<dl class="typelist inheritedMembers">
<dt>Inherited Members</dt>
<dd>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.gettype">object.GetType()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.memberwiseclone">object.MemberwiseClone()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object-system-object)">object.Equals(object, object)</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.referenceequals">object.ReferenceEquals(object, object)</a>
</div>
</dd></dl>
<h2 class="section" id="constructors">Constructors
</h2>
<a id="EchoHub_Core_DTOs_UserOperationResult__ctor_" data-uid="EchoHub.Core.DTOs.UserOperationResult.#ctor*"></a>
<h3 id="EchoHub_Core_DTOs_UserOperationResult__ctor_EchoHub_Core_DTOs_UserOperationResult_" data-uid="EchoHub.Core.DTOs.UserOperationResult.#ctor(EchoHub.Core.DTOs.UserOperationResult)">
UserOperationResult(UserOperationResult)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/CommonDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">protected UserOperationResult(UserOperationResult original)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>original</code> <a class="xref" href="EchoHub.Core.DTOs.UserOperationResult.html">UserOperationResult</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_DTOs_UserOperationResult__ctor_" data-uid="EchoHub.Core.DTOs.UserOperationResult.#ctor*"></a>
<h3 id="EchoHub_Core_DTOs_UserOperationResult__ctor_EchoHub_Core_DTOs_UserProfileDto_System_Nullable_EchoHub_Core_DTOs_UserError__System_String_" data-uid="EchoHub.Core.DTOs.UserOperationResult.#ctor(EchoHub.Core.DTOs.UserProfileDto,System.Nullable{EchoHub.Core.DTOs.UserError},System.String)">
UserOperationResult(UserProfileDto?, UserError?, string?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/CommonDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public UserOperationResult(UserProfileDto? User, UserError? Error, string? ErrorMessage)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>User</code> <a class="xref" href="EchoHub.Core.DTOs.UserProfileDto.html">UserProfileDto</a></dt>
<dd></dd>
<dt><code>Error</code> <a class="xref" href="EchoHub.Core.DTOs.UserError.html">UserError</a>?</dt>
<dd></dd>
<dt><code>ErrorMessage</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h2 class="section" id="properties">Properties
</h2>
<a id="EchoHub_Core_DTOs_UserOperationResult_EqualityContract_" data-uid="EchoHub.Core.DTOs.UserOperationResult.EqualityContract*"></a>
<h3 id="EchoHub_Core_DTOs_UserOperationResult_EqualityContract" data-uid="EchoHub.Core.DTOs.UserOperationResult.EqualityContract">
EqualityContract
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/CommonDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">protected virtual Type EqualityContract { get; }</code></pre>
</div>
<h4 class="section">Property Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.type">Type</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_DTOs_UserOperationResult_Error_" data-uid="EchoHub.Core.DTOs.UserOperationResult.Error*"></a>
<h3 id="EchoHub_Core_DTOs_UserOperationResult_Error" data-uid="EchoHub.Core.DTOs.UserOperationResult.Error">
Error
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/CommonDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public UserError? Error { get; init; }</code></pre>
</div>
<h4 class="section">Property Value</h4>
<dl class="parameters">
<dt><a class="xref" href="EchoHub.Core.DTOs.UserError.html">UserError</a>?</dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_DTOs_UserOperationResult_ErrorMessage_" data-uid="EchoHub.Core.DTOs.UserOperationResult.ErrorMessage*"></a>
<h3 id="EchoHub_Core_DTOs_UserOperationResult_ErrorMessage" data-uid="EchoHub.Core.DTOs.UserOperationResult.ErrorMessage">
ErrorMessage
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/CommonDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public string? ErrorMessage { get; init; }</code></pre>
</div>
<h4 class="section">Property Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_DTOs_UserOperationResult_IsSuccess_" data-uid="EchoHub.Core.DTOs.UserOperationResult.IsSuccess*"></a>
<h3 id="EchoHub_Core_DTOs_UserOperationResult_IsSuccess" data-uid="EchoHub.Core.DTOs.UserOperationResult.IsSuccess">
IsSuccess
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/CommonDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public bool IsSuccess { get; }</code></pre>
</div>
<h4 class="section">Property Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.boolean">bool</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_DTOs_UserOperationResult_User_" data-uid="EchoHub.Core.DTOs.UserOperationResult.User*"></a>
<h3 id="EchoHub_Core_DTOs_UserOperationResult_User" data-uid="EchoHub.Core.DTOs.UserOperationResult.User">
User
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/CommonDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public UserProfileDto? User { get; init; }</code></pre>
</div>
<h4 class="section">Property Value</h4>
<dl class="parameters">
<dt><a class="xref" href="EchoHub.Core.DTOs.UserProfileDto.html">UserProfileDto</a></dt>
<dd></dd>
</dl>
<h2 class="section" id="methods">Methods
</h2>
<a id="EchoHub_Core_DTOs_UserOperationResult_Deconstruct_" data-uid="EchoHub.Core.DTOs.UserOperationResult.Deconstruct*"></a>
<h3 id="EchoHub_Core_DTOs_UserOperationResult_Deconstruct_EchoHub_Core_DTOs_UserProfileDto__System_Nullable_EchoHub_Core_DTOs_UserError___System_String__" data-uid="EchoHub.Core.DTOs.UserOperationResult.Deconstruct(EchoHub.Core.DTOs.UserProfileDto@,System.Nullable{EchoHub.Core.DTOs.UserError}@,System.String@)">
Deconstruct(out UserProfileDto?, out UserError?, out string?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/CommonDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public void Deconstruct(out UserProfileDto? User, out UserError? Error, out string? ErrorMessage)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>User</code> <a class="xref" href="EchoHub.Core.DTOs.UserProfileDto.html">UserProfileDto</a></dt>
<dd></dd>
<dt><code>Error</code> <a class="xref" href="EchoHub.Core.DTOs.UserError.html">UserError</a>?</dt>
<dd></dd>
<dt><code>ErrorMessage</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_DTOs_UserOperationResult_Equals_" data-uid="EchoHub.Core.DTOs.UserOperationResult.Equals*"></a>
<h3 id="EchoHub_Core_DTOs_UserOperationResult_Equals_EchoHub_Core_DTOs_UserOperationResult_" data-uid="EchoHub.Core.DTOs.UserOperationResult.Equals(EchoHub.Core.DTOs.UserOperationResult)">
Equals(UserOperationResult?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/CommonDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public virtual bool Equals(UserOperationResult? other)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>other</code> <a class="xref" href="EchoHub.Core.DTOs.UserOperationResult.html">UserOperationResult</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.boolean">bool</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_DTOs_UserOperationResult_Equals_" data-uid="EchoHub.Core.DTOs.UserOperationResult.Equals*"></a>
<h3 id="EchoHub_Core_DTOs_UserOperationResult_Equals_System_Object_" data-uid="EchoHub.Core.DTOs.UserOperationResult.Equals(System.Object)">
Equals(object?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/CommonDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public override bool Equals(object? obj)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>obj</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object">object</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.boolean">bool</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_DTOs_UserOperationResult_Fail_" data-uid="EchoHub.Core.DTOs.UserOperationResult.Fail*"></a>
<h3 id="EchoHub_Core_DTOs_UserOperationResult_Fail_EchoHub_Core_DTOs_UserError_System_String_" data-uid="EchoHub.Core.DTOs.UserOperationResult.Fail(EchoHub.Core.DTOs.UserError,System.String)">
Fail(UserError, string)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/CommonDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static UserOperationResult Fail(UserError error, string message)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>error</code> <a class="xref" href="EchoHub.Core.DTOs.UserError.html">UserError</a></dt>
<dd></dd>
<dt><code>message</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="EchoHub.Core.DTOs.UserOperationResult.html">UserOperationResult</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_DTOs_UserOperationResult_GetHashCode_" data-uid="EchoHub.Core.DTOs.UserOperationResult.GetHashCode*"></a>
<h3 id="EchoHub_Core_DTOs_UserOperationResult_GetHashCode" data-uid="EchoHub.Core.DTOs.UserOperationResult.GetHashCode">
GetHashCode()
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/CommonDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public override int GetHashCode()</code></pre>
</div>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.int32">int</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_DTOs_UserOperationResult_PrintMembers_" data-uid="EchoHub.Core.DTOs.UserOperationResult.PrintMembers*"></a>
<h3 id="EchoHub_Core_DTOs_UserOperationResult_PrintMembers_System_Text_StringBuilder_" data-uid="EchoHub.Core.DTOs.UserOperationResult.PrintMembers(System.Text.StringBuilder)">
PrintMembers(StringBuilder)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/CommonDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">protected virtual bool PrintMembers(StringBuilder builder)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>builder</code> <span class="xref">StringBuilder</span></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.boolean">bool</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_DTOs_UserOperationResult_Success_" data-uid="EchoHub.Core.DTOs.UserOperationResult.Success*"></a>
<h3 id="EchoHub_Core_DTOs_UserOperationResult_Success_EchoHub_Core_DTOs_UserProfileDto_" data-uid="EchoHub.Core.DTOs.UserOperationResult.Success(EchoHub.Core.DTOs.UserProfileDto)">
Success(UserProfileDto)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/CommonDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static UserOperationResult Success(UserProfileDto user)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>user</code> <a class="xref" href="EchoHub.Core.DTOs.UserProfileDto.html">UserProfileDto</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="EchoHub.Core.DTOs.UserOperationResult.html">UserOperationResult</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_DTOs_UserOperationResult_ToString_" data-uid="EchoHub.Core.DTOs.UserOperationResult.ToString*"></a>
<h3 id="EchoHub_Core_DTOs_UserOperationResult_ToString" data-uid="EchoHub.Core.DTOs.UserOperationResult.ToString">
ToString()
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/CommonDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public override string ToString()</code></pre>
</div>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h2 class="section" id="operators">Operators
</h2>
<a id="EchoHub_Core_DTOs_UserOperationResult_op_Equality_" data-uid="EchoHub.Core.DTOs.UserOperationResult.op_Equality*"></a>
<h3 id="EchoHub_Core_DTOs_UserOperationResult_op_Equality_EchoHub_Core_DTOs_UserOperationResult_EchoHub_Core_DTOs_UserOperationResult_" data-uid="EchoHub.Core.DTOs.UserOperationResult.op_Equality(EchoHub.Core.DTOs.UserOperationResult,EchoHub.Core.DTOs.UserOperationResult)">
operator ==(UserOperationResult?, UserOperationResult?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/CommonDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static bool operator ==(UserOperationResult? left, UserOperationResult? right)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>left</code> <a class="xref" href="EchoHub.Core.DTOs.UserOperationResult.html">UserOperationResult</a></dt>
<dd></dd>
<dt><code>right</code> <a class="xref" href="EchoHub.Core.DTOs.UserOperationResult.html">UserOperationResult</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.boolean">bool</a></dt>
<dd></dd>
</dl>
<a id="EchoHub_Core_DTOs_UserOperationResult_op_Inequality_" data-uid="EchoHub.Core.DTOs.UserOperationResult.op_Inequality*"></a>
<h3 id="EchoHub_Core_DTOs_UserOperationResult_op_Inequality_EchoHub_Core_DTOs_UserOperationResult_EchoHub_Core_DTOs_UserOperationResult_" data-uid="EchoHub.Core.DTOs.UserOperationResult.op_Inequality(EchoHub.Core.DTOs.UserOperationResult,EchoHub.Core.DTOs.UserOperationResult)">
operator !=(UserOperationResult?, UserOperationResult?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/CommonDtos.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static bool operator !=(UserOperationResult? left, UserOperationResult? right)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>left</code> <a class="xref" href="EchoHub.Core.DTOs.UserOperationResult.html">UserOperationResult</a></dt>
<dd></dd>
<dt><code>right</code> <a class="xref" href="EchoHub.Core.DTOs.UserOperationResult.html">UserOperationResult</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.boolean">bool</a></dt>
<dd></dd>
</dl>
</article>
<div class="contribution d-print-none">
<a href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/CommonDtos.cs" class="edit-link">Edit this page</a>
</div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<div class='footer-custom'><div class='footer-inner'><span class='footer-brand'>EchoHub</span><span class='footer-sep'>&middot;</span><a href='https://github.com/HueByte/EchoHub'>GitHub</a><span class='footer-sep'>&middot;</span><a href='https://echohub.voidcube.cloud'>Website</a><span class='footer-sep'>&middot;</span><span class='footer-credit'>Built with <a href='https://dotnet.github.io/docfx'>DocFX</a></span></div></div>
</div>
</div>
</footer>
</body>
</html>
+12
View File
@@ -138,6 +138,10 @@ Classes
<dt><a class="xref" href="EchoHub.Core.DTOs.ErrorResponse.html">ErrorResponse</a></dt>
<dd></dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="EchoHub.Core.DTOs.JoinChannelResult.html">JoinChannelResult</a></dt>
<dd></dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="EchoHub.Core.DTOs.KickRequest.html">KickRequest</a></dt>
<dd></dd>
@@ -198,6 +202,10 @@ Classes
<dt><a class="xref" href="EchoHub.Core.DTOs.UserDto.html">UserDto</a></dt>
<dd></dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="EchoHub.Core.DTOs.UserOperationResult.html">UserOperationResult</a></dt>
<dd></dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="EchoHub.Core.DTOs.UserPresenceDto.html">UserPresenceDto</a></dt>
<dd></dd>
@@ -213,6 +221,10 @@ Enums
<dt><a class="xref" href="EchoHub.Core.DTOs.ChannelError.html">ChannelError</a></dt>
<dd></dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="EchoHub.Core.DTOs.UserError.html">UserError</a></dt>
<dd></dd>
</dl>
</article>
@@ -461,8 +461,8 @@ Class IrcBroadcaster <a class="header-action link-secondary" title="View source
<a id="EchoHub_Server_Irc_IrcBroadcaster_SendUserJoinedAsync_" data-uid="EchoHub.Server.Irc.IrcBroadcaster.SendUserJoinedAsync*"></a>
<h3 id="EchoHub_Server_Irc_IrcBroadcaster_SendUserJoinedAsync_System_String_System_String_System_String_" data-uid="EchoHub.Server.Irc.IrcBroadcaster.SendUserJoinedAsync(System.String,System.String,System.String)">
SendUserJoinedAsync(string, string, string?)
<h3 id="EchoHub_Server_Irc_IrcBroadcaster_SendUserJoinedAsync_System_String_System_String_EchoHub_Core_DTOs_UserPresenceDto_System_String_" data-uid="EchoHub.Server.Irc.IrcBroadcaster.SendUserJoinedAsync(System.String,System.String,EchoHub.Core.DTOs.UserPresenceDto,System.String)">
SendUserJoinedAsync(string, string, UserPresenceDto?, string?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Server.Irc/IrcBroadcaster.cs"><i class="bi bi-code-slash"></i></a>
</h3>
@@ -470,7 +470,7 @@ Class IrcBroadcaster <a class="header-action link-secondary" title="View source
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public Task SendUserJoinedAsync(string channelName, string username, string? excludeConnectionId = null)</code></pre>
<pre><code class="lang-csharp hljs">public Task SendUserJoinedAsync(string channelName, string username, UserPresenceDto? presence, string? excludeConnectionId = null)</code></pre>
</div>
<h4 class="section">Parameters</h4>
@@ -479,6 +479,8 @@ Class IrcBroadcaster <a class="header-action link-secondary" title="View source
<dd></dd>
<dt><code>username</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dt><code>presence</code> <a class="xref" href="../core/EchoHub.Core.DTOs.UserPresenceDto.html">UserPresenceDto</a></dt>
<dd></dd>
<dt><code>excludeConnectionId</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
@@ -151,8 +151,8 @@ Class IrcCommandHandler <a class="header-action link-secondary" title="View sou
<a id="EchoHub_Server_Irc_IrcCommandHandler__ctor_" data-uid="EchoHub.Server.Irc.IrcCommandHandler.#ctor*"></a>
<h3 id="EchoHub_Server_Irc_IrcCommandHandler__ctor_EchoHub_Server_Irc_IrcClientConnection_EchoHub_Server_Irc_IrcOptions_EchoHub_Core_Contracts_IChatService_EchoHub_Core_Contracts_IChannelService_EchoHub_Core_Contracts_IMessageEncryptionService_Microsoft_Extensions_Logging_ILogger_" data-uid="EchoHub.Server.Irc.IrcCommandHandler.#ctor(EchoHub.Server.Irc.IrcClientConnection,EchoHub.Server.Irc.IrcOptions,EchoHub.Core.Contracts.IChatService,EchoHub.Core.Contracts.IChannelService,EchoHub.Core.Contracts.IMessageEncryptionService,Microsoft.Extensions.Logging.ILogger)">
IrcCommandHandler(IrcClientConnection, IrcOptions, IChatService, IChannelService, IMessageEncryptionService, ILogger)
<h3 id="EchoHub_Server_Irc_IrcCommandHandler__ctor_EchoHub_Server_Irc_IrcClientConnection_EchoHub_Server_Irc_IrcOptions_EchoHub_Core_Contracts_IChatService_EchoHub_Core_Contracts_IUserService_EchoHub_Core_Contracts_IChannelService_EchoHub_Core_Contracts_IMessageEncryptionService_Microsoft_Extensions_Logging_ILogger_" data-uid="EchoHub.Server.Irc.IrcCommandHandler.#ctor(EchoHub.Server.Irc.IrcClientConnection,EchoHub.Server.Irc.IrcOptions,EchoHub.Core.Contracts.IChatService,EchoHub.Core.Contracts.IUserService,EchoHub.Core.Contracts.IChannelService,EchoHub.Core.Contracts.IMessageEncryptionService,Microsoft.Extensions.Logging.ILogger)">
IrcCommandHandler(IrcClientConnection, IrcOptions, IChatService, IUserService, IChannelService, IMessageEncryptionService, ILogger)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Server.Irc/IrcCommandHandler.cs"><i class="bi bi-code-slash"></i></a>
</h3>
@@ -160,7 +160,7 @@ Class IrcCommandHandler <a class="header-action link-secondary" title="View sou
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public IrcCommandHandler(IrcClientConnection conn, IrcOptions options, IChatService chatService, IChannelService channelService, IMessageEncryptionService encryption, ILogger logger)</code></pre>
<pre><code class="lang-csharp hljs">public IrcCommandHandler(IrcClientConnection conn, IrcOptions options, IChatService chatService, IUserService userService, IChannelService channelService, IMessageEncryptionService encryption, ILogger logger)</code></pre>
</div>
<h4 class="section">Parameters</h4>
@@ -171,6 +171,8 @@ Class IrcCommandHandler <a class="header-action link-secondary" title="View sou
<dd></dd>
<dt><code>chatService</code> <a class="xref" href="../core/EchoHub.Core.Contracts.IChatService.html">IChatService</a></dt>
<dd></dd>
<dt><code>userService</code> <a class="xref" href="../core/EchoHub.Core.Contracts.IUserService.html">IUserService</a></dt>
<dd></dd>
<dt><code>channelService</code> <a class="xref" href="../core/EchoHub.Core.Contracts.IChannelService.html">IChannelService</a></dt>
<dd></dd>
<dt><code>encryption</code> <a class="xref" href="../core/EchoHub.Core.Contracts.IMessageEncryptionService.html">IMessageEncryptionService</a></dt>
@@ -221,6 +221,42 @@ Class JwtTokenService <a class="header-action link-secondary" title="View sourc
</h2>
<a id="EchoHub_Server_Auth_JwtTokenService_GenerateAccessToken_" data-uid="EchoHub.Server.Auth.JwtTokenService.GenerateAccessToken*"></a>
<h3 id="EchoHub_Server_Auth_JwtTokenService_GenerateAccessToken_EchoHub_Core_DTOs_UserProfileDto_" data-uid="EchoHub.Server.Auth.JwtTokenService.GenerateAccessToken(EchoHub.Core.DTOs.UserProfileDto)">
GenerateAccessToken(UserProfileDto)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Server/Auth/JwtTokenService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public (string Token, DateTimeOffset ExpiresAt) GenerateAccessToken(UserProfileDto profile)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>profile</code> <a class="xref" href="../core/EchoHub.Core.DTOs.UserProfileDto.html">UserProfileDto</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt>(<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.valuetuple-system.string,system.datetimeoffset-.token">Token</a>, <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.datetimeoffset">DateTimeOffset</a> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.valuetuple-system.string,system.datetimeoffset-.expiresat">ExpiresAt</a>)</dt>
<dd></dd>
</dl>
<a id="EchoHub_Server_Auth_JwtTokenService_GenerateAccessToken_" data-uid="EchoHub.Server.Auth.JwtTokenService.GenerateAccessToken*"></a>
<h3 id="EchoHub_Server_Auth_JwtTokenService_GenerateAccessToken_EchoHub_Core_Models_User_" data-uid="EchoHub.Server.Auth.JwtTokenService.GenerateAccessToken(EchoHub.Core.Models.User)">
@@ -158,8 +158,8 @@ public class AuthController : ControllerBase</code></pre>
<a id="EchoHub_Server_Controllers_AuthController__ctor_" data-uid="EchoHub.Server.Controllers.AuthController.#ctor*"></a>
<h3 id="EchoHub_Server_Controllers_AuthController__ctor_EchoHub_Server_Data_EchoHubDbContext_EchoHub_Server_Auth_JwtTokenService_" data-uid="EchoHub.Server.Controllers.AuthController.#ctor(EchoHub.Server.Data.EchoHubDbContext,EchoHub.Server.Auth.JwtTokenService)">
AuthController(EchoHubDbContext, JwtTokenService)
<h3 id="EchoHub_Server_Controllers_AuthController__ctor_EchoHub_Server_Data_EchoHubDbContext_EchoHub_Server_Auth_JwtTokenService_EchoHub_Core_Contracts_IUserService_" data-uid="EchoHub.Server.Controllers.AuthController.#ctor(EchoHub.Server.Data.EchoHubDbContext,EchoHub.Server.Auth.JwtTokenService,EchoHub.Core.Contracts.IUserService)">
AuthController(EchoHubDbContext, JwtTokenService, IUserService)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Server/Controllers/AuthController.cs"><i class="bi bi-code-slash"></i></a>
</h3>
@@ -167,7 +167,7 @@ public class AuthController : ControllerBase</code></pre>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public AuthController(EchoHubDbContext db, JwtTokenService jwt)</code></pre>
<pre><code class="lang-csharp hljs">public AuthController(EchoHubDbContext db, JwtTokenService jwt, IUserService userService)</code></pre>
</div>
<h4 class="section">Parameters</h4>
@@ -176,6 +176,8 @@ public class AuthController : ControllerBase</code></pre>
<dd></dd>
<dt><code>jwt</code> <a class="xref" href="EchoHub.Server.Auth.JwtTokenService.html">JwtTokenService</a></dt>
<dd></dd>
<dt><code>userService</code> <a class="xref" href="../core/EchoHub.Core.Contracts.IUserService.html">IUserService</a></dt>
<dd></dd>
</dl>
@@ -159,8 +159,8 @@ public class UsersController : ControllerBase</code></pre>
<a id="EchoHub_Server_Controllers_UsersController__ctor_" data-uid="EchoHub.Server.Controllers.UsersController.#ctor*"></a>
<h3 id="EchoHub_Server_Controllers_UsersController__ctor_EchoHub_Server_Data_EchoHubDbContext_EchoHub_Server_Services_ImageToAsciiService_" data-uid="EchoHub.Server.Controllers.UsersController.#ctor(EchoHub.Server.Data.EchoHubDbContext,EchoHub.Server.Services.ImageToAsciiService)">
UsersController(EchoHubDbContext, ImageToAsciiService)
<h3 id="EchoHub_Server_Controllers_UsersController__ctor_EchoHub_Core_Contracts_IUserService_EchoHub_Server_Services_ImageToAsciiService_" data-uid="EchoHub.Server.Controllers.UsersController.#ctor(EchoHub.Core.Contracts.IUserService,EchoHub.Server.Services.ImageToAsciiService)">
UsersController(IUserService, ImageToAsciiService)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Server/Controllers/UsersController.cs"><i class="bi bi-code-slash"></i></a>
</h3>
@@ -168,12 +168,12 @@ public class UsersController : ControllerBase</code></pre>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public UsersController(EchoHubDbContext db, ImageToAsciiService asciiService)</code></pre>
<pre><code class="lang-csharp hljs">public UsersController(IUserService userService, ImageToAsciiService asciiService)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>db</code> <a class="xref" href="EchoHub.Server.Data.EchoHubDbContext.html">EchoHubDbContext</a></dt>
<dt><code>userService</code> <a class="xref" href="../core/EchoHub.Core.Contracts.IUserService.html">IUserService</a></dt>
<dd></dd>
<dt><code>asciiService</code> <a class="xref" href="EchoHub.Server.Services.ImageToAsciiService.html">ImageToAsciiService</a></dt>
<dd></dd>
+2 -2
View File
@@ -283,7 +283,7 @@ public class ChatHub : Hub&lt;IEchoHubClient&gt;, IDisposable</code></pre>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public Task&lt;List&lt;MessageDto&gt;&gt; JoinChannel(string channelName)</code></pre>
<pre><code class="lang-csharp hljs">public Task&lt;JoinChannelResult&gt; JoinChannel(string channelName)</code></pre>
</div>
<h4 class="section">Parameters</h4>
@@ -294,7 +294,7 @@ public class ChatHub : Hub&lt;IEchoHubClient&gt;, IDisposable</code></pre>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><span class="xref">Task</span>&lt;<span class="xref">List</span>&lt;<a class="xref" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/ChatDtos.cs">MessageDto</a>&gt;&gt;</dt>
<dt><span class="xref">Task</span>&lt;<a class="xref" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/ChatDtos.cs">JoinChannelResult</a>&gt;</dt>
<dd></dd>
</dl>
@@ -205,44 +205,6 @@ Class ChatService <a class="header-action link-secondary" title="View source" h
</h2>
<a id="EchoHub_Server_Services_ChatService_AuthenticateUserAsync_" data-uid="EchoHub.Server.Services.ChatService.AuthenticateUserAsync*"></a>
<h3 id="EchoHub_Server_Services_ChatService_AuthenticateUserAsync_System_String_System_String_" data-uid="EchoHub.Server.Services.ChatService.AuthenticateUserAsync(System.String,System.String)">
AuthenticateUserAsync(string, string)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Server/Services/ChatService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public Task&lt;(Guid UserId, string Username)?&gt; AuthenticateUserAsync(string username, string password)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>username</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dt><code>password</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><span class="xref">Task</span>&lt;(<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.guid">Guid</a> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.valuetuple-system.guid,system.string-.userid">UserId</a>, <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.valuetuple-system.guid,system.string-.username">Username</a>)?&gt;</dt>
<dd></dd>
</dl>
<a id="EchoHub_Server_Services_ChatService_BroadcastChannelUpdatedAsync_" data-uid="EchoHub.Server.Services.ChatService.BroadcastChannelUpdatedAsync*"></a>
<h3 id="EchoHub_Server_Services_ChatService_BroadcastChannelUpdatedAsync_EchoHub_Core_DTOs_ChannelDto_System_String_" data-uid="EchoHub.Server.Services.ChatService.BroadcastChannelUpdatedAsync(EchoHub.Core.DTOs.ChannelDto,System.String)">
@@ -429,42 +391,6 @@ Class ChatService <a class="header-action link-secondary" title="View source" h
<a id="EchoHub_Server_Services_ChatService_GetUserProfileAsync_" data-uid="EchoHub.Server.Services.ChatService.GetUserProfileAsync*"></a>
<h3 id="EchoHub_Server_Services_ChatService_GetUserProfileAsync_System_String_" data-uid="EchoHub.Server.Services.ChatService.GetUserProfileAsync(System.String)">
GetUserProfileAsync(string)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Server/Services/ChatService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public Task&lt;UserProfileDto?&gt; GetUserProfileAsync(string username)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>username</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><span class="xref">Task</span>&lt;<a class="xref" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/ProfileDtos.cs">UserProfileDto</a>&gt;</dt>
<dd></dd>
</dl>
<a id="EchoHub_Server_Services_ChatService_JoinChannelAsync_" data-uid="EchoHub.Server.Services.ChatService.JoinChannelAsync*"></a>
<h3 id="EchoHub_Server_Services_ChatService_JoinChannelAsync_System_String_System_Guid_System_String_System_String_" data-uid="EchoHub.Server.Services.ChatService.JoinChannelAsync(System.String,System.Guid,System.String,System.String)">
@@ -0,0 +1,258 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Class MuteExpirationService | EchoHub Documentation </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Class MuteExpirationService | EchoHub Documentation ">
<meta name="description" content="Background service that periodically unmutes users whose timed mute has expired.">
<link rel="icon" href="../../images/hue_icon.svg">
<link rel="stylesheet" href="../../public/docfx.min.css">
<link rel="stylesheet" href="../../public/main.css">
<meta name="docfx:navrel" content="../../toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../../">
<meta name="docfx:docurl" content="https://github.com/HueByte/EchoHub/new/master/apiSpec/new?filename=EchoHub_Server_Services_MuteExpirationService.md&amp;value=---%0Auid%3A%20EchoHub.Server.Services.MuteExpirationService%0Asummary%3A%20&#39;*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax&#39;%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="ManagedReference">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../../index.html">
<img id="logo" class="svg" src="../../images/hue_icon.svg" alt="EchoHub">
EchoHub
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="EchoHub.Server.Services.MuteExpirationService">
<h1 id="EchoHub_Server_Services_MuteExpirationService" data-uid="EchoHub.Server.Services.MuteExpirationService" class="text-break">
Class MuteExpirationService <a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Server/Services/MuteExpirationService.cs"><i class="bi bi-code-slash"></i></a>
</h1>
<div class="facts text-secondary">
<dl><dt>Namespace</dt><dd><a class="xref" href="EchoHub.html">EchoHub</a>.<a class="xref" href="EchoHub.Server.html">Server</a>.<a class="xref" href="EchoHub.Server.Services.html">Services</a></dd></dl>
<dl><dt>Assembly</dt><dd>EchoHub.Server.dll</dd></dl>
</div>
<div class="markdown summary"><p>Background service that periodically unmutes users whose timed mute has expired.</p>
</div>
<div class="markdown conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public sealed class MuteExpirationService : BackgroundService, IDisposable</code></pre>
</div>
<dl class="typelist inheritance">
<dt>Inheritance</dt>
<dd>
<div><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object">object</a></div>
<div><span class="xref">BackgroundService</span></div>
<div><span class="xref">MuteExpirationService</span></div>
</dd>
</dl>
<dl class="typelist implements">
<dt>Implements</dt>
<dd>
<div><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.idisposable">IDisposable</a></div>
</dd>
</dl>
<dl class="typelist inheritedMembers">
<dt>Inherited Members</dt>
<dd>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.gettype">object.GetType()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.tostring">object.ToString()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object)">object.Equals(object)</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object-system-object)">object.Equals(object, object)</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.referenceequals">object.ReferenceEquals(object, object)</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.gethashcode">object.GetHashCode()</a>
</div>
</dd></dl>
<h2 class="section" id="constructors">Constructors
</h2>
<a id="EchoHub_Server_Services_MuteExpirationService__ctor_" data-uid="EchoHub.Server.Services.MuteExpirationService.#ctor*"></a>
<h3 id="EchoHub_Server_Services_MuteExpirationService__ctor_Microsoft_Extensions_DependencyInjection_IServiceScopeFactory_Microsoft_Extensions_Logging_ILogger_EchoHub_Server_Services_MuteExpirationService__" data-uid="EchoHub.Server.Services.MuteExpirationService.#ctor(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory,Microsoft.Extensions.Logging.ILogger{EchoHub.Server.Services.MuteExpirationService})">
MuteExpirationService(IServiceScopeFactory, ILogger&lt;MuteExpirationService&gt;)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Server/Services/MuteExpirationService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public MuteExpirationService(IServiceScopeFactory scopeFactory, ILogger&lt;MuteExpirationService&gt; logger)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>scopeFactory</code> <span class="xref">IServiceScopeFactory</span></dt>
<dd></dd>
<dt><code>logger</code> <span class="xref">ILogger</span>&lt;<a class="xref" href="EchoHub.Server.Services.MuteExpirationService.html">MuteExpirationService</a>&gt;</dt>
<dd></dd>
</dl>
<h2 class="section" id="methods">Methods
</h2>
<a id="EchoHub_Server_Services_MuteExpirationService_ExecuteAsync_" data-uid="EchoHub.Server.Services.MuteExpirationService.ExecuteAsync*"></a>
<h3 id="EchoHub_Server_Services_MuteExpirationService_ExecuteAsync_System_Threading_CancellationToken_" data-uid="EchoHub.Server.Services.MuteExpirationService.ExecuteAsync(System.Threading.CancellationToken)">
ExecuteAsync(CancellationToken)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Server/Services/MuteExpirationService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">protected override Task ExecuteAsync(CancellationToken stoppingToken)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>stoppingToken</code> <span class="xref">CancellationToken</span></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><span class="xref">Task</span></dt>
<dd></dd>
</dl>
</article>
<div class="contribution d-print-none">
<a href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Server/Services/MuteExpirationService.cs" class="edit-link">Edit this page</a>
</div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<div class='footer-custom'><div class='footer-inner'><span class='footer-brand'>EchoHub</span><span class='footer-sep'>&middot;</span><a href='https://github.com/HueByte/EchoHub'>GitHub</a><span class='footer-sep'>&middot;</span><a href='https://echohub.voidcube.cloud'>Website</a><span class='footer-sep'>&middot;</span><span class='footer-credit'>Built with <a href='https://dotnet.github.io/docfx'>DocFX</a></span></div></div>
</div>
</div>
</footer>
</body>
</html>
@@ -461,8 +461,8 @@ Class SignalRBroadcaster <a class="header-action link-secondary" title="View so
<a id="EchoHub_Server_Services_SignalRBroadcaster_SendUserJoinedAsync_" data-uid="EchoHub.Server.Services.SignalRBroadcaster.SendUserJoinedAsync*"></a>
<h3 id="EchoHub_Server_Services_SignalRBroadcaster_SendUserJoinedAsync_System_String_System_String_System_String_" data-uid="EchoHub.Server.Services.SignalRBroadcaster.SendUserJoinedAsync(System.String,System.String,System.String)">
SendUserJoinedAsync(string, string, string?)
<h3 id="EchoHub_Server_Services_SignalRBroadcaster_SendUserJoinedAsync_System_String_System_String_EchoHub_Core_DTOs_UserPresenceDto_System_String_" data-uid="EchoHub.Server.Services.SignalRBroadcaster.SendUserJoinedAsync(System.String,System.String,EchoHub.Core.DTOs.UserPresenceDto,System.String)">
SendUserJoinedAsync(string, string, UserPresenceDto?, string?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Server/Services/SignalRBroadcaster.cs"><i class="bi bi-code-slash"></i></a>
</h3>
@@ -470,7 +470,7 @@ Class SignalRBroadcaster <a class="header-action link-secondary" title="View so
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public Task SendUserJoinedAsync(string channelName, string username, string? excludeConnectionId = null)</code></pre>
<pre><code class="lang-csharp hljs">public Task SendUserJoinedAsync(string channelName, string username, UserPresenceDto? presence, string? excludeConnectionId = null)</code></pre>
</div>
<h4 class="section">Parameters</h4>
@@ -479,6 +479,8 @@ Class SignalRBroadcaster <a class="header-action link-secondary" title="View so
<dd></dd>
<dt><code>username</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dt><code>presence</code> <a class="xref" href="../core/EchoHub.Core.DTOs.UserPresenceDto.html">UserPresenceDto</a></dt>
<dd></dd>
<dt><code>excludeConnectionId</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
@@ -0,0 +1,451 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Class UserService | EchoHub Documentation </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Class UserService | EchoHub Documentation ">
<link rel="icon" href="../../images/hue_icon.svg">
<link rel="stylesheet" href="../../public/docfx.min.css">
<link rel="stylesheet" href="../../public/main.css">
<meta name="docfx:navrel" content="../../toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../../">
<meta name="docfx:docurl" content="https://github.com/HueByte/EchoHub/new/master/apiSpec/new?filename=EchoHub_Server_Services_UserService.md&amp;value=---%0Auid%3A%20EchoHub.Server.Services.UserService%0Asummary%3A%20&#39;*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax&#39;%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="ManagedReference">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../../index.html">
<img id="logo" class="svg" src="../../images/hue_icon.svg" alt="EchoHub">
EchoHub
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="EchoHub.Server.Services.UserService">
<h1 id="EchoHub_Server_Services_UserService" data-uid="EchoHub.Server.Services.UserService" class="text-break">
Class UserService <a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Server/Services/UserService.cs"><i class="bi bi-code-slash"></i></a>
</h1>
<div class="facts text-secondary">
<dl><dt>Namespace</dt><dd><a class="xref" href="EchoHub.html">EchoHub</a>.<a class="xref" href="EchoHub.Server.html">Server</a>.<a class="xref" href="EchoHub.Server.Services.html">Services</a></dd></dl>
<dl><dt>Assembly</dt><dd>EchoHub.Server.dll</dd></dl>
</div>
<div class="markdown summary"></div>
<div class="markdown conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public class UserService : IUserService</code></pre>
</div>
<dl class="typelist inheritance">
<dt>Inheritance</dt>
<dd>
<div><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object">object</a></div>
<div><span class="xref">UserService</span></div>
</dd>
</dl>
<dl class="typelist implements">
<dt>Implements</dt>
<dd>
<div><a class="xref" href="../core/EchoHub.Core.Contracts.IUserService.html">IUserService</a></div>
</dd>
</dl>
<dl class="typelist inheritedMembers">
<dt>Inherited Members</dt>
<dd>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.gettype">object.GetType()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.memberwiseclone">object.MemberwiseClone()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.tostring">object.ToString()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object)">object.Equals(object)</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object-system-object)">object.Equals(object, object)</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.referenceequals">object.ReferenceEquals(object, object)</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.gethashcode">object.GetHashCode()</a>
</div>
</dd></dl>
<h2 class="section" id="constructors">Constructors
</h2>
<a id="EchoHub_Server_Services_UserService__ctor_" data-uid="EchoHub.Server.Services.UserService.#ctor*"></a>
<h3 id="EchoHub_Server_Services_UserService__ctor_Microsoft_Extensions_DependencyInjection_IServiceScopeFactory_" data-uid="EchoHub.Server.Services.UserService.#ctor(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory)">
UserService(IServiceScopeFactory)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Server/Services/UserService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public UserService(IServiceScopeFactory scopeFactory)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>scopeFactory</code> <span class="xref">IServiceScopeFactory</span></dt>
<dd></dd>
</dl>
<h2 class="section" id="methods">Methods
</h2>
<a id="EchoHub_Server_Services_UserService_AuthenticateUserAsync_" data-uid="EchoHub.Server.Services.UserService.AuthenticateUserAsync*"></a>
<h3 id="EchoHub_Server_Services_UserService_AuthenticateUserAsync_System_String_System_String_" data-uid="EchoHub.Server.Services.UserService.AuthenticateUserAsync(System.String,System.String)">
AuthenticateUserAsync(string, string)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Server/Services/UserService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public Task&lt;UserOperationResult&gt; AuthenticateUserAsync(string username, string password)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>username</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dt><code>password</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><span class="xref">Task</span>&lt;<a class="xref" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/CommonDtos.cs">UserOperationResult</a>&gt;</dt>
<dd></dd>
</dl>
<a id="EchoHub_Server_Services_UserService_GetUserByIdAsync_" data-uid="EchoHub.Server.Services.UserService.GetUserByIdAsync*"></a>
<h3 id="EchoHub_Server_Services_UserService_GetUserByIdAsync_System_Guid_" data-uid="EchoHub.Server.Services.UserService.GetUserByIdAsync(System.Guid)">
GetUserByIdAsync(Guid)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Server/Services/UserService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public Task&lt;UserProfileDto?&gt; GetUserByIdAsync(Guid userId)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>userId</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.guid">Guid</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><span class="xref">Task</span>&lt;<a class="xref" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/ProfileDtos.cs">UserProfileDto</a>&gt;</dt>
<dd></dd>
</dl>
<a id="EchoHub_Server_Services_UserService_GetUserProfileAsync_" data-uid="EchoHub.Server.Services.UserService.GetUserProfileAsync*"></a>
<h3 id="EchoHub_Server_Services_UserService_GetUserProfileAsync_System_String_" data-uid="EchoHub.Server.Services.UserService.GetUserProfileAsync(System.String)">
GetUserProfileAsync(string)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Server/Services/UserService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public Task&lt;UserProfileDto?&gt; GetUserProfileAsync(string username)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>username</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><span class="xref">Task</span>&lt;<a class="xref" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/ProfileDtos.cs">UserProfileDto</a>&gt;</dt>
<dd></dd>
</dl>
<a id="EchoHub_Server_Services_UserService_RegisterUserAsync_" data-uid="EchoHub.Server.Services.UserService.RegisterUserAsync*"></a>
<h3 id="EchoHub_Server_Services_UserService_RegisterUserAsync_System_String_System_String_System_String_" data-uid="EchoHub.Server.Services.UserService.RegisterUserAsync(System.String,System.String,System.String)">
RegisterUserAsync(string, string, string?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Server/Services/UserService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public Task&lt;UserOperationResult&gt; RegisterUserAsync(string username, string password, string? displayName = null)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>username</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dt><code>password</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dt><code>displayName</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><span class="xref">Task</span>&lt;<a class="xref" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/CommonDtos.cs">UserOperationResult</a>&gt;</dt>
<dd></dd>
</dl>
<a id="EchoHub_Server_Services_UserService_SetAvatarAsync_" data-uid="EchoHub.Server.Services.UserService.SetAvatarAsync*"></a>
<h3 id="EchoHub_Server_Services_UserService_SetAvatarAsync_System_Guid_System_String_" data-uid="EchoHub.Server.Services.UserService.SetAvatarAsync(System.Guid,System.String)">
SetAvatarAsync(Guid, string)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Server/Services/UserService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public Task&lt;UserOperationResult&gt; SetAvatarAsync(Guid userId, string asciiArt)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>userId</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.guid">Guid</a></dt>
<dd></dd>
<dt><code>asciiArt</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><span class="xref">Task</span>&lt;<a class="xref" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/CommonDtos.cs">UserOperationResult</a>&gt;</dt>
<dd></dd>
</dl>
<a id="EchoHub_Server_Services_UserService_UpdateProfileAsync_" data-uid="EchoHub.Server.Services.UserService.UpdateProfileAsync*"></a>
<h3 id="EchoHub_Server_Services_UserService_UpdateProfileAsync_System_Guid_System_String_System_String_System_String_" data-uid="EchoHub.Server.Services.UserService.UpdateProfileAsync(System.Guid,System.String,System.String,System.String)">
UpdateProfileAsync(Guid, string?, string?, string?)
<a class="header-action link-secondary" title="View source" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Server/Services/UserService.cs"><i class="bi bi-code-slash"></i></a>
</h3>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public Task&lt;UserOperationResult&gt; UpdateProfileAsync(Guid userId, string? displayName, string? bio, string? nicknameColor)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>userId</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.guid">Guid</a></dt>
<dd></dd>
<dt><code>displayName</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dt><code>bio</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
<dt><code>nicknameColor</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><span class="xref">Task</span>&lt;<a class="xref" href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Core/DTOs/CommonDtos.cs">UserOperationResult</a>&gt;</dt>
<dd></dd>
</dl>
</article>
<div class="contribution d-print-none">
<a href="https://github.com/HueByte/EchoHub/blob/master/src/EchoHub.Server/Services/UserService.cs" class="edit-link">Edit this page</a>
</div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<div class='footer-custom'><div class='footer-inner'><span class='footer-brand'>EchoHub</span><span class='footer-sep'>&middot;</span><a href='https://github.com/HueByte/EchoHub'>GitHub</a><span class='footer-sep'>&middot;</span><a href='https://echohub.voidcube.cloud'>Website</a><span class='footer-sep'>&middot;</span><span class='footer-credit'>Built with <a href='https://dotnet.github.io/docfx'>DocFX</a></span></div></div>
</div>
</div>
</footer>
</body>
</html>
+9
View File
@@ -126,6 +126,11 @@ Classes
<dt><a class="xref" href="EchoHub.Server.Services.MessageEncryptionService.html">MessageEncryptionService</a></dt>
<dd></dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="EchoHub.Server.Services.MuteExpirationService.html">MuteExpirationService</a></dt>
<dd><p>Background service that periodically unmutes users whose timed mute has expired.</p>
</dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="EchoHub.Server.Services.PresenceTracker.html">PresenceTracker</a></dt>
<dd></dd>
@@ -138,6 +143,10 @@ Classes
<dt><a class="xref" href="EchoHub.Server.Services.SignalRBroadcaster.html">SignalRBroadcaster</a></dt>
<dd></dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="EchoHub.Server.Services.UserService.html">UserService</a></dt>
<dd></dd>
</dl>
</article>
+27
View File
@@ -81,6 +81,9 @@
<li>
<a href="client/EchoHub.Client.Services.AudioPlaybackService.html" name="" title="AudioPlaybackService">AudioPlaybackService</a>
</li>
<li>
<a href="client/EchoHub.Client.Services.BackupInfo.html" name="" title="BackupInfo">BackupInfo</a>
</li>
<li>
<a href="client/EchoHub.Client.Services.ClientEncryptionService.html" name="" title="ClientEncryptionService">ClientEncryptionService</a>
</li>
@@ -90,6 +93,12 @@
<li>
<a href="client/EchoHub.Client.Services.NotificationSoundService.html" name="" title="NotificationSoundService">NotificationSoundService</a>
</li>
<li>
<a href="client/EchoHub.Client.Services.PathSetup.html" name="" title="PathSetup">PathSetup</a>
</li>
<li>
<a href="client/EchoHub.Client.Services.UpdateBackupService.html" name="" title="UpdateBackupService">UpdateBackupService</a>
</li>
<li>
<a href="client/EchoHub.Client.Services.UpdateChecker.html" name="" title="UpdateChecker">UpdateChecker</a>
</li>
@@ -275,6 +284,9 @@
<li>
<a href="core/EchoHub.Core.Contracts.IMessageEncryptionService.html" name="" title="IMessageEncryptionService">IMessageEncryptionService</a>
</li>
<li>
<a href="core/EchoHub.Core.Contracts.IUserService.html" name="" title="IUserService">IUserService</a>
</li>
</ul>
</li>
<li>
@@ -318,6 +330,9 @@
<li>
<a href="core/EchoHub.Core.DTOs.ErrorResponse.html" name="" title="ErrorResponse">ErrorResponse</a>
</li>
<li>
<a href="core/EchoHub.Core.DTOs.JoinChannelResult.html" name="" title="JoinChannelResult">JoinChannelResult</a>
</li>
<li>
<a href="core/EchoHub.Core.DTOs.KickRequest.html" name="" title="KickRequest">KickRequest</a>
</li>
@@ -363,6 +378,12 @@
<li>
<a href="core/EchoHub.Core.DTOs.UserDto.html" name="" title="UserDto">UserDto</a>
</li>
<li>
<a href="core/EchoHub.Core.DTOs.UserError.html" name="" title="UserError">UserError</a>
</li>
<li>
<a href="core/EchoHub.Core.DTOs.UserOperationResult.html" name="" title="UserOperationResult">UserOperationResult</a>
</li>
<li>
<a href="core/EchoHub.Core.DTOs.UserPresenceDto.html" name="" title="UserPresenceDto">UserPresenceDto</a>
</li>
@@ -538,6 +559,9 @@
<li>
<a href="server/EchoHub.Server.Services.MessageEncryptionService.html" name="" title="MessageEncryptionService">MessageEncryptionService</a>
</li>
<li>
<a href="server/EchoHub.Server.Services.MuteExpirationService.html" name="" title="MuteExpirationService">MuteExpirationService</a>
</li>
<li>
<a href="server/EchoHub.Server.Services.PresenceTracker.html" name="" title="PresenceTracker">PresenceTracker</a>
</li>
@@ -547,6 +571,9 @@
<li>
<a href="server/EchoHub.Server.Services.SignalRBroadcaster.html" name="" title="SignalRBroadcaster">SignalRBroadcaster</a>
</li>
<li>
<a href="server/EchoHub.Server.Services.UserService.html" name="" title="UserService">UserService</a>
</li>
</ul>
</li>
<li>
+1 -1
View File
File diff suppressed because one or more lines are too long
+279
View File
@@ -0,0 +1,279 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Docker | EchoHub Documentation </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Docker | EchoHub Documentation ">
<link rel="icon" href="../images/hue_icon.svg">
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:rel" content="../">
<meta name="docfx:docurl" content="https://github.com/HueByte/EchoHub/blob/master/docs/#L1">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../index.html">
<img id="logo" class="svg" src="../images/hue_icon.svg" alt="EchoHub">
EchoHub
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="">
<h1 id="docker">Docker</h1>
<h2 id="quick-start">Quick Start</h2>
<pre><code class="lang-bash">cp .env.example .env # create your config
docker compose up -d # start the server
</code></pre>
<p>On first run the server automatically generates JWT and encryption keys, creates the database, and seeds a <code>#general</code> channel. Connect with the EchoHub client to <code>http://localhost:5000</code>.</p>
<h3 id="using-a-pre-built-image">Using a Pre-built Image</h3>
<p>Instead of building locally, you can pull from GHCR. In <code>docker-compose.yml</code>, replace the <code>build</code> block:</p>
<pre><code class="lang-yaml">services:
echohub-server:
image: ghcr.io/huebyte/echohub-server:latest
# build:
# context: ./src
# dockerfile: EchoHub.Server/Dockerfile
</code></pre>
<h2 id="configuration">Configuration</h2>
<p>All settings are configured through the <code>.env</code> file. These are ASP.NET Core environment variables that override <code>appsettings.json</code>.</p>
<table>
<thead>
<tr>
<th>Variable</th>
<th>Default</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>Server__Name</code></td>
<td>My EchoHub Server</td>
<td>Display name for your server</td>
</tr>
<tr>
<td><code>Server__Description</code></td>
<td>A self-hosted EchoHub chat server</td>
<td>Server description</td>
</tr>
<tr>
<td><code>Server__PublicServer</code></td>
<td><code>false</code></td>
<td>List on the <a href="https://echohub.voidcube.cloud/servers">public directory</a></td>
</tr>
<tr>
<td><code>Server__PublicHost</code></td>
<td><em>(empty)</em></td>
<td>Public address for the directory listing</td>
</tr>
<tr>
<td><code>Server__Admins__0</code></td>
<td><em>(empty)</em></td>
<td>Admin username (use <code>__1</code>, <code>__2</code> for more)</td>
</tr>
<tr>
<td><code>Jwt__Secret</code></td>
<td><em>(auto-generated)</em></td>
<td>JWT signing key. Auto-generated on first run</td>
</tr>
<tr>
<td><code>Encryption__Key</code></td>
<td><em>(auto-generated)</em></td>
<td>AES encryption key. Auto-generated on first run</td>
</tr>
<tr>
<td><code>Encryption__EncryptDatabase</code></td>
<td><code>false</code></td>
<td>Encrypt message content in the database</td>
</tr>
<tr>
<td><code>Storage__CleanupIntervalHours</code></td>
<td><code>1</code></td>
<td>How often to clean expired uploads</td>
</tr>
<tr>
<td><code>Storage__RetentionDays</code></td>
<td><code>30</code></td>
<td>Days to keep uploaded files</td>
</tr>
<tr>
<td><code>Irc__Enabled</code></td>
<td><code>false</code></td>
<td>Enable the IRC gateway</td>
</tr>
<tr>
<td><code>Irc__Port</code></td>
<td><code>6667</code></td>
<td>IRC plain-text port</td>
</tr>
<tr>
<td><code>Irc__TlsEnabled</code></td>
<td><code>false</code></td>
<td>Enable IRC over TLS</td>
</tr>
<tr>
<td><code>Irc__TlsPort</code></td>
<td><code>6697</code></td>
<td>IRC TLS port</td>
</tr>
<tr>
<td><code>Irc__ServerName</code></td>
<td><code>echohub</code></td>
<td>IRC server name shown to clients</td>
</tr>
<tr>
<td><code>Irc__Motd</code></td>
<td>Welcome to EchoHub IRC Gateway!</td>
<td>Message of the day</td>
</tr>
<tr>
<td><code>Serilog__MinimumLevel__Default</code></td>
<td><code>Information</code></td>
<td>Log level (<code>Debug</code>, <code>Warning</code>, etc.)</td>
</tr>
</tbody>
</table>
<h2 id="persistent-data">Persistent Data</h2>
<p>All server state lives in a single Docker volume mounted at <code>/app/data</code>:</p>
<pre><code class="lang-text">/app/data/
├── appsettings.json # generated config with JWT/encryption keys
├── echohub.db # SQLite database
├── uploads/ # uploaded files and avatars
└── logs/ # rolling log files (14-day retention)
</code></pre>
<h3 id="backup">Backup</h3>
<pre><code class="lang-bash"># stop the server to ensure a consistent snapshot
docker compose stop
# copy the data volume to a local directory
docker cp echohub-server:/app/data ./backup
docker compose start
</code></pre>
<h2 id="irc-gateway">IRC Gateway</h2>
<p>To enable IRC, set these in your <code>.env</code>:</p>
<pre><code class="lang-env">Irc__Enabled=true
</code></pre>
<p>Then uncomment the port in <code>docker-compose.yml</code>:</p>
<pre><code class="lang-yaml">ports:
- &quot;5000:5000&quot;
- &quot;6697:6697&quot; # IRC (TLS encrypted, preferred)
</code></pre>
<p>For TLS, also set:</p>
<pre><code class="lang-env">Irc__TlsEnabled=true
Irc__TlsCertPath=/app/data/cert.pfx
Irc__TlsCertPassword=your_password
</code></pre>
<p>Mount your certificate into the data volume or bind-mount it directly.</p>
<p>IRC users must have an existing EchoHub account. See <a href="getting-started.html#connect-via-irc">Getting Started</a> for client connection examples.</p>
<h2 id="updating">Updating</h2>
<pre><code class="lang-bash"># if using pre-built images
docker compose pull
docker compose up -d
# if building locally
docker compose build
docker compose up -d
</code></pre>
<p>Data persists across updates since it lives in the named volume.</p>
<h2 id="troubleshooting">Troubleshooting</h2>
<p><strong>Port already in use</strong> -- Another process is using port 5000. Change the host port in <code>docker-compose.yml</code>:</p>
<pre><code class="lang-yaml">ports:
- &quot;8080:5000&quot; # access via http://localhost:8080
</code></pre>
<p><strong>Permission denied on volume</strong> -- The container runs as a non-root <code>echohub</code> user (UID 999). If using bind mounts instead of named volumes, ensure the directory is writable.</p>
<p><strong>View logs</strong> -- Check the container output:</p>
<pre><code class="lang-bash">docker compose logs -f echohub-server
</code></pre>
<p>File-based logs are also available inside the volume at <code>/app/data/logs/</code>.</p>
</article>
<div class="contribution d-print-none">
<a href="https://github.com/HueByte/EchoHub/blob/master/docs/#L1" class="edit-link">Edit this page</a>
</div>
<div class="next-article d-print-none border-top" id="nextArticle"></div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<div class='footer-custom'><div class='footer-inner'><span class='footer-brand'>EchoHub</span><span class='footer-sep'>&middot;</span><a href='https://github.com/HueByte/EchoHub'>GitHub</a><span class='footer-sep'>&middot;</span><a href='https://echohub.voidcube.cloud'>Website</a><span class='footer-sep'>&middot;</span><span class='footer-credit'>Built with <a href='https://dotnet.github.io/docfx'>DocFX</a></span></div></div>
</div>
</div>
</footer>
</body>
</html>
+25 -10
View File
@@ -87,24 +87,39 @@
<article data-uid="">
<h1 id="getting-started">Getting Started</h1>
<h2 id="prerequisites">Prerequisites</h2>
<ul>
<li><a href="https://dotnet.microsoft.com/download">.NET 10 SDK</a></li>
</ul>
<p>Or grab a self-contained binary from <a href="https://github.com/HueByte/EchoHub/releases">Releases</a> -- no runtime needed.</p>
<h2 id="run-the-server">Run the Server</h2>
<h2 id="install-the-client">Install the Client</h2>
<h3 id="windows-chocolatey">Windows (Chocolatey)</h3>
<pre><code class="lang-bash">choco install echohub
</code></pre>
<h3 id="linux--macos">Linux / macOS</h3>
<pre><code class="lang-bash">curl -sSfL https://raw.githubusercontent.com/HueByte/EchoHub/master/scripts/install.sh | sh
</code></pre>
<p>To install a specific version or to a custom directory:</p>
<pre><code class="lang-bash">curl -sSfL .../install.sh | sh -s -- --version 0.2.8
curl -sSfL .../install.sh | sh -s -- --install-dir /opt/echohub
</code></pre>
<h3 id="manual-download">Manual Download</h3>
<p>Grab a self-contained binary from <a href="https://github.com/HueByte/EchoHub/releases">Releases</a> -- no runtime needed.</p>
<h2 id="host-a-server">Host a Server</h2>
<h3 id="docker">Docker</h3>
<p>The quickest way to host a server:</p>
<pre><code class="lang-bash">cp .env.example .env
docker compose up -d
</code></pre>
<p>See the <a href="docker.html">Docker guide</a> for configuration, pre-built images, and more.</p>
<h3 id="from-source">From Source</h3>
<pre><code class="lang-bash">dotnet run --project src/EchoHub.Server
</code></pre>
<p>Requires <a href="https://dotnet.microsoft.com/download">.NET 10 SDK</a>.</p>
<p>On first run, the server automatically:</p>
<ol>
<li>Creates <code>appsettings.json</code> from the example config</li>
<li>Generates a secure JWT secret</li>
<li>Creates the SQLite database with a <code>#general</code> channel</li>
</ol>
<h2 id="run-the-client">Run the Client</h2>
<pre><code class="lang-bash">dotnet run --project src/EchoHub.Client
</code></pre>
<p>Connect to a server, register an account, and start chatting.</p>
<h2 id="usage">Usage</h2>
<p>After installing the client, run <code>echohub</code> (or <code>dotnet run --project src/EchoHub.Client</code> from source).
Connect to a server, register an account, and start chatting.</p>
<h2 id="connect-via-irc">Connect via IRC</h2>
<p>Enable the IRC gateway in the server's <code>appsettings.json</code>:</p>
<pre><code class="lang-json">{
+3
View File
@@ -15,6 +15,9 @@
<li>
<a href="getting-started.html" name="" title="Getting Started">Getting Started</a>
</li>
<li>
<a href="docker.html" name="" title="Docker">Docker</a>
</li>
<li>
<a href="architecture.html" name="" title="Architecture">Architecture</a>
</li>
+1 -1
View File
@@ -1,2 +1,2 @@
{"items":[{"name":"Getting Started","href":"getting-started.html","topicHref":"getting-started.html"},{"name":"Architecture","href":"architecture.html","topicHref":"architecture.html"},{"name":"Encryption","href":"encryption.html","topicHref":"encryption.html"},{"name":"Notification Sounds","href":"notification-sounds.html","topicHref":"notification-sounds.html"}]}
{"items":[{"name":"Getting Started","href":"getting-started.html","topicHref":"getting-started.html"},{"name":"Docker","href":"docker.html","topicHref":"docker.html"},{"name":"Architecture","href":"architecture.html","topicHref":"architecture.html"},{"name":"Encryption","href":"encryption.html","topicHref":"encryption.html"},{"name":"Notification Sounds","href":"notification-sounds.html","topicHref":"notification-sounds.html"}]}
+3
View File
@@ -90,6 +90,9 @@
<p>Release history for EchoHub.</p>
<h2 id="releases">Releases</h2>
<ul>
<li><a href="v0.2.8.html">v0.2.8</a> - Docker Support, IRC Account Creation &amp; BOM Fix</li>
<li><a href="v0.2.7.html">v0.2.7</a> - User List Fix &amp; Terminal.Gui NuGet Migration</li>
<li><a href="v0.2.6.html">v0.2.6</a> - Major Refactoring &amp; Code Organization</li>
<li><a href="v0.2.5.html">v0.2.5</a> - Session Persistence, Auto-Updates, Audio &amp; Transparent Theme</li>
<li><a href="v0.2.4.html">v0.2.4</a> - E2E Message Encryption</li>
<li><a href="v0.2.3.html">v0.2.3</a> - Moderation, Embeds &amp; UI Overhaul</li>
+3
View File
@@ -15,6 +15,9 @@
<li>
<a href="index.html" name="" title="Overview">Overview</a>
</li>
<li>
<a href="v0.2.8.html" name="" title="v0.2.8">v0.2.8</a>
</li>
<li>
<a href="v0.2.7.html" name="" title="v0.2.7">v0.2.7</a>
</li>
+1 -1
View File
@@ -1,2 +1,2 @@
{"items":[{"name":"Overview","href":"index.html","topicHref":"index.html"},{"name":"v0.2.7","href":"v0.2.7.html","topicHref":"v0.2.7.html"},{"name":"v0.2.6","href":"v0.2.6.html","topicHref":"v0.2.6.html"},{"name":"v0.2.5","href":"v0.2.5.html","topicHref":"v0.2.5.html"},{"name":"v0.2.4","href":"v0.2.4.html","topicHref":"v0.2.4.html"},{"name":"v0.2.3","href":"v0.2.3.html","topicHref":"v0.2.3.html"},{"name":"v0.2.2","href":"v0.2.2.html","topicHref":"v0.2.2.html"},{"name":"v0.2.1","href":"v0.2.1.html","topicHref":"v0.2.1.html"},{"name":"v0.2.0","href":"v0.2.0.html","topicHref":"v0.2.0.html"},{"name":"v0.1.1","href":"v0.1.1.html","topicHref":"v0.1.1.html"},{"name":"v0.1.0","href":"v0.1.0.html","topicHref":"v0.1.0.html"}]}
{"items":[{"name":"Overview","href":"index.html","topicHref":"index.html"},{"name":"v0.2.8","href":"v0.2.8.html","topicHref":"v0.2.8.html"},{"name":"v0.2.7","href":"v0.2.7.html","topicHref":"v0.2.7.html"},{"name":"v0.2.6","href":"v0.2.6.html","topicHref":"v0.2.6.html"},{"name":"v0.2.5","href":"v0.2.5.html","topicHref":"v0.2.5.html"},{"name":"v0.2.4","href":"v0.2.4.html","topicHref":"v0.2.4.html"},{"name":"v0.2.3","href":"v0.2.3.html","topicHref":"v0.2.3.html"},{"name":"v0.2.2","href":"v0.2.2.html","topicHref":"v0.2.2.html"},{"name":"v0.2.1","href":"v0.2.1.html","topicHref":"v0.2.1.html"},{"name":"v0.2.0","href":"v0.2.0.html","topicHref":"v0.2.0.html"},{"name":"v0.1.1","href":"v0.1.1.html","topicHref":"v0.1.1.html"},{"name":"v0.1.0","href":"v0.1.0.html","topicHref":"v0.1.0.html"}]}
+172
View File
@@ -0,0 +1,172 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>v0.2.8 | EchoHub Documentation </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="v0.2.8 | EchoHub Documentation ">
<link rel="icon" href="../images/hue_icon.svg">
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:rel" content="../">
<meta name="docfx:docurl" content="https://github.com/HueByte/EchoHub/blob/master/docs/#L1">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../index.html">
<img id="logo" class="svg" src="../images/hue_icon.svg" alt="EchoHub">
EchoHub
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="">
<h1 id="v028">v0.2.8</h1>
<h2 id="bug-fixes">Bug Fixes</h2>
<ul>
<li>Fix memory leak — <code>HttpResponseMessage</code> objects never disposed in <code>ApiClient</code>, leaking TCP connections and content buffers on every API call (especially on failed connection attempts)</li>
<li>Fix 401 retry leak — <code>AuthenticatedGetAsync</code>/<code>AuthenticatedRequestAsync</code> leaked the original response when retrying after token refresh</li>
<li>Fix connection failure cleanup — <code>ConnectionManager.ConnectAsync</code> now properly disposes <code>ApiClient</code> and <code>EchoHubConnection</code> on any failure path (previously only cleaned up on saved-token auth failures)</li>
<li>Fix IRC gateway sending UTF-8 BOM on first message, breaking CAP negotiation and SASL auth for all clients</li>
<li>Handle <code>AUTHENTICATE *</code> (SASL abort) instead of crashing on invalid base64</li>
<li>Fix userlist not refreshing when creating a new channel — now fetches online users after channel creation</li>
<li>Fix unmute timer not working — add <code>MuteExpirationService</code> background job that proactively unmutes users when their timed mute expires (previously only checked on message send)</li>
<li>Fix missing space between mod/admin role icon and username in the userlist</li>
<li>Fix invisible users still visible in the userlist — <code>GetOnlineUsersAsync</code> now filters invisible users; server skips <code>UserJoined</code> broadcast for invisible users</li>
<li>Fix invisible→online transition — user reappears in cached userlist when switching from invisible back to a visible status</li>
<li>Fix thread safety — <code>_channelUsers</code> presence cache now protected by <code>Lock</code> to prevent races between SignalR events and background fetches</li>
<li>Fix <code>@mention</code> regex matching email addresses and <code>#channel</code> regex matching hex colors / issue numbers — both now use lookbehind and letter-requirement guards</li>
<li>Fix <code>ParseThemeColor</code> accepting non-hex characters — now validates <code>[0-9a-fA-F]</code> digits</li>
<li>Fix ghost channel when trying to join a channel that doesn't exist</li>
</ul>
<h2 id="new-features">New Features</h2>
<ul>
<li>Add Docker support for EchoHub.Server — <code>docker compose up -d</code> for easy self-hosting with persistent volume for database, uploads, and logs</li>
<li>IRC account creation — connecting with a new username auto-registers the account (PASS and SASL PLAIN)</li>
<li>Auto-updater rollback — pre-update backup created automatically before each update; restore via File &gt; Rollback menu or <code>--rollback</code> CLI flag</li>
<li>Update failure recovery — if an update fails mid-extraction, offers to restore from the backup immediately</li>
<li>Defensive Unix permission check — verify execute permission on startup after auto-update (defense-in-depth)</li>
<li>Clickable usernames — press Enter on a username in the userlist or message sender to view their profile</li>
<li>Clickable @mentions — press Enter on a message containing <code>@username</code> to open that user's profile</li>
<li>Clickable #channels — press Enter on a message containing <code>#channel</code> to join/switch to that channel; <code>#channel</code> references are now highlighted in chat</li>
<li>Embed theme colors — embed vertical border line now uses the source site's <code>theme-color</code> meta tag when available</li>
<li>Stateful userlist — user presence is cached per channel and updated incrementally via SignalR events instead of re-fetching the full list on every join/leave/status change</li>
</ul>
<h2 id="security">Security</h2>
<ul>
<li>Restrict file auto-open — only safe file types (video, PDF, text) are opened with the system default app; all other files are downloaded to temp without executing (prevents script execution via <code>.bat</code>, <code>.exe</code>, etc.)</li>
</ul>
<h2 id="refactoring">Refactoring</h2>
<ul>
<li>Extract <code>IUserService</code>/<code>UserService</code> — consolidate user registration, authentication, and profile management into a dedicated service, eliminating duplicated logic between <code>AuthController</code> and <code>ChatService</code></li>
<li>IRC gateway now checks ban status during authentication (previously skipped)</li>
<li>EchoHubSpace directory updates — server now only sends user count when it actually changes instead of every 30 seconds</li>
<li><code>ChatHub.JoinChannel</code> now returns <code>JoinChannelResult</code> instead of <code>List&lt;MessageDto&gt;</code> to allow for better error handling</li>
</ul>
<h2 id="distribution">Distribution</h2>
<ul>
<li>Add Chocolatey package — <code>choco install echohub</code> for Windows users, auto-published from CI on each release</li>
<li>Add Linux/macOS install script — <code>curl -sSfL .../install.sh | sh</code> with automatic OS/arch detection</li>
</ul>
<h2 id="documentation">Documentation</h2>
<ul>
<li>Add Flows section — Mermaid sequence diagrams documenting all major request/event flows (auth, connection, messaging, channels, moderation, file upload, link embeds, server directory) with inline code references</li>
</ul>
<h2 id="ci">CI</h2>
<ul>
<li>Add Docker workflow — builds and pushes multi-arch (<code>amd64</code>/<code>arm64</code>) server image to GHCR on release</li>
<li>Add <code>linux-arm64</code> builds to release pipeline — server and client binaries for ARM Linux (Raspberry Pi, cloud ARM instances)</li>
<li>Automate Chocolatey package publishing in release workflow (checksum calculation, pack, push)</li>
</ul>
</article>
<div class="contribution d-print-none">
<a href="https://github.com/HueByte/EchoHub/blob/master/docs/#L1" class="edit-link">Edit this page</a>
</div>
<div class="next-article d-print-none border-top" id="nextArticle"></div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<div class='footer-custom'><div class='footer-inner'><span class='footer-brand'>EchoHub</span><span class='footer-sep'>&middot;</span><a href='https://github.com/HueByte/EchoHub'>GitHub</a><span class='footer-sep'>&middot;</span><a href='https://echohub.voidcube.cloud'>Website</a><span class='footer-sep'>&middot;</span><span class='footer-credit'>Built with <a href='https://dotnet.github.io/docfx'>DocFX</a></span></div></div>
</div>
</div>
</footer>
</body>
</html>
+352
View File
@@ -0,0 +1,352 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Authentication | EchoHub Documentation </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Authentication | EchoHub Documentation ">
<link rel="icon" href="../images/hue_icon.svg">
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:rel" content="../">
<meta name="docfx:docurl" content="https://github.com/HueByte/EchoHub/blob/master/docs/#L1">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../index.html">
<img id="logo" class="svg" src="../images/hue_icon.svg" alt="EchoHub">
EchoHub
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="">
<h1 id="authentication">Authentication</h1>
<h2 id="user-registration">User Registration</h2>
<p>A new user creates an account on a server. The client sends credentials via REST,
the server hashes the password, issues JWT tokens, and the client stores the
refresh token for &quot;Remember Me&quot; sessions.</p>
<pre><code class="lang-mermaid">sequenceDiagram
participant UI as ConnectDialog
participant AO as AppOrchestrator
participant CM as ConnectionManager
participant API as ApiClient
participant Auth as AuthController
participant US as UserService
participant JWT as JwtTokenService
participant DB as SQLite
UI-&gt;&gt;AO: ConnectDialogResult(IsRegister: true)
AO-&gt;&gt;CM: ConnectAsync(dialogResult)
CM-&gt;&gt;API: RegisterAsync(username, password)
API-&gt;&gt;Auth: POST /api/auth/register
Auth-&gt;&gt;US: RegisterUserAsync(username, password, displayName)
US-&gt;&gt;US: Validate (regex, length, uniqueness)
US-&gt;&gt;DB: INSERT User (BCrypt hash)
US--&gt;&gt;Auth: UserOperationResult.Success
Auth-&gt;&gt;JWT: GenerateAccessToken(user)
JWT--&gt;&gt;Auth: (token, expiresAt) [15 min]
Auth-&gt;&gt;JWT: GenerateRefreshToken()
JWT--&gt;&gt;Auth: Base64 random (64 bytes)
Auth-&gt;&gt;DB: INSERT RefreshToken (SHA256 hash)
Auth--&gt;&gt;API: LoginResponse
API-&gt;&gt;API: SetTokens() — store in memory + set Bearer header
API--&gt;&gt;CM: LoginResponse
CM-&gt;&gt;CM: Wire OnTokensRefreshed for config persistence
CM-&gt;&gt;CM: Continue to connection setup (see Connection Flow)
</code></pre>
<p><strong>Code references:</strong></p>
<table>
<thead>
<tr>
<th>Step</th>
<th>File</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr>
<td>Dialog UI</td>
<td><code>src/EchoHub.Client/UI/Dialogs/ConnectDialog.cs</code></td>
<td>Lines 251-268 (register handler)</td>
</tr>
<tr>
<td>Orchestrator entry</td>
<td><code>src/EchoHub.Client/AppOrchestrator.cs</code></td>
<td>Lines 550-592 (<code>HandleConnect</code>)</td>
</tr>
<tr>
<td>ConnectionManager auth</td>
<td><code>src/EchoHub.Client/Services/ConnectionManager.cs</code></td>
<td>Lines 74-76 (register branch)</td>
</tr>
<tr>
<td>ApiClient register</td>
<td><code>src/EchoHub.Client/Services/ApiClient.cs</code></td>
<td>Lines 32-43 (<code>RegisterAsync</code>)</td>
</tr>
<tr>
<td>AuthController register</td>
<td><code>src/EchoHub.Server/Controllers/AuthController.cs</code></td>
<td>Lines 28-49</td>
</tr>
<tr>
<td>UserService register</td>
<td><code>src/EchoHub.Server/Services/UserService.cs</code></td>
<td>Lines 20-59 (<code>RegisterUserAsync</code>)</td>
</tr>
<tr>
<td>JWT generation</td>
<td><code>src/EchoHub.Server/Auth/JwtTokenService.cs</code></td>
<td>Lines 30-53 (access), 80-86 (refresh)</td>
</tr>
<tr>
<td>Token persistence</td>
<td><code>src/EchoHub.Client/AppOrchestrator.cs</code></td>
<td>Lines 1039-1053 (<code>SaveServerToConfig</code>)</td>
</tr>
</tbody>
</table>
<hr>
<h2 id="user-login">User Login</h2>
<p>Returning user authenticates with username/password or a saved refresh token.</p>
<pre><code class="lang-mermaid">sequenceDiagram
participant UI as ConnectDialog
participant CM as ConnectionManager
participant API as ApiClient
participant Auth as AuthController
participant US as UserService
participant DB as SQLite
alt Saved refresh token (Remember Me)
UI-&gt;&gt;CM: ConnectDialogResult(SavedRefreshToken: &quot;...&quot;)
CM-&gt;&gt;API: LoginWithRefreshTokenAsync()
API-&gt;&gt;Auth: POST /api/auth/refresh
Auth-&gt;&gt;DB: Lookup token by SHA256 hash
Auth-&gt;&gt;DB: Revoke old token, issue new pair
Auth--&gt;&gt;API: LoginResponse (rotated tokens)
else Username + Password
UI-&gt;&gt;CM: ConnectDialogResult(IsRegister: false)
CM-&gt;&gt;API: LoginAsync(username, password)
API-&gt;&gt;Auth: POST /api/auth/login
Auth-&gt;&gt;US: AuthenticateUserAsync(username, password)
US-&gt;&gt;DB: Fetch user, BCrypt.Verify(password, hash)
US-&gt;&gt;DB: Update LastSeenAt
US--&gt;&gt;Auth: UserOperationResult.Success
Auth--&gt;&gt;API: LoginResponse
end
API-&gt;&gt;API: SetTokens()
</code></pre>
<p><strong>Code references:</strong></p>
<table>
<thead>
<tr>
<th>Step</th>
<th>File</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr>
<td>Login button handler</td>
<td><code>src/EchoHub.Client/UI/Dialogs/ConnectDialog.cs</code></td>
<td>Lines 214-249</td>
</tr>
<tr>
<td>Saved token branch</td>
<td><code>src/EchoHub.Client/Services/ConnectionManager.cs</code></td>
<td>Lines 69-71</td>
</tr>
<tr>
<td>Password branch</td>
<td><code>src/EchoHub.Client/Services/ConnectionManager.cs</code></td>
<td>Lines 78-80</td>
</tr>
<tr>
<td>ApiClient login</td>
<td><code>src/EchoHub.Client/Services/ApiClient.cs</code></td>
<td>Lines 45-56 (<code>LoginAsync</code>)</td>
</tr>
<tr>
<td>AuthController login</td>
<td><code>src/EchoHub.Server/Controllers/AuthController.cs</code></td>
<td>Lines 51-72</td>
</tr>
<tr>
<td>AuthController refresh</td>
<td><code>src/EchoHub.Server/Controllers/AuthController.cs</code></td>
<td>Lines 74-108</td>
</tr>
<tr>
<td>UserService authenticate</td>
<td><code>src/EchoHub.Server/Services/UserService.cs</code></td>
<td>Lines 61-83</td>
</tr>
</tbody>
</table>
<hr>
<h2 id="token-refresh">Token Refresh</h2>
<p>Access tokens expire after 15 minutes. The client auto-refreshes transparently
before requests and on 401 responses. Refresh tokens are rotated on each use.</p>
<pre><code class="lang-mermaid">sequenceDiagram
participant SR as SignalR / HTTP Request
participant API as ApiClient
participant Auth as AuthController
participant DB as SQLite
participant Config as config.json
SR-&gt;&gt;API: GetValidTokenAsync() or HTTP 401
API-&gt;&gt;API: Token expires within 60s?
alt Proactive refresh (SignalR token provider)
API-&gt;&gt;Auth: POST /api/auth/refresh (old refresh token)
else Reactive refresh (HTTP 401 retry)
API-&gt;&gt;Auth: POST /api/auth/refresh (old refresh token)
end
Auth-&gt;&gt;DB: Lookup by SHA256 hash
Auth-&gt;&gt;DB: Revoke old refresh token
Auth-&gt;&gt;DB: INSERT new RefreshToken
Auth--&gt;&gt;API: LoginResponse (new token pair)
API-&gt;&gt;API: SetTokens() — update Bearer header
API--&gt;&gt;API: Fire OnTokensRefreshed event
API--&gt;&gt;Config: Persist new refresh token (if Remember Me)
API-&gt;&gt;SR: Retry original request with new token
</code></pre>
<p><strong>Code references:</strong></p>
<table>
<thead>
<tr>
<th>Step</th>
<th>File</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr>
<td>Proactive check</td>
<td><code>src/EchoHub.Client/Services/ApiClient.cs</code></td>
<td>Lines 110-129 (<code>GetValidTokenAsync</code>)</td>
</tr>
<tr>
<td>Reactive 401 retry (GET)</td>
<td><code>src/EchoHub.Client/Services/ApiClient.cs</code></td>
<td>Lines 338-358 (<code>AuthenticatedGetAsync</code>)</td>
</tr>
<tr>
<td>Reactive 401 retry (POST/PUT/DELETE)</td>
<td><code>src/EchoHub.Client/Services/ApiClient.cs</code></td>
<td>Lines 364-384 (<code>AuthenticatedRequestAsync</code>)</td>
</tr>
<tr>
<td>Refresh HTTP call</td>
<td><code>src/EchoHub.Client/Services/ApiClient.cs</code></td>
<td>Lines 58-71 (<code>RefreshTokenAsync</code>)</td>
</tr>
<tr>
<td>SignalR token provider</td>
<td><code>src/EchoHub.Client/Services/EchoHubConnection.cs</code></td>
<td>Line 37 (<code>AccessTokenProvider</code>)</td>
</tr>
<tr>
<td>Server-side rotation</td>
<td><code>src/EchoHub.Server/Controllers/AuthController.cs</code></td>
<td>Lines 74-108</td>
</tr>
<tr>
<td>Token persistence callback</td>
<td><code>src/EchoHub.Client/Services/ConnectionManager.cs</code></td>
<td>Lines 253-264</td>
</tr>
</tbody>
</table>
</article>
<div class="contribution d-print-none">
<a href="https://github.com/HueByte/EchoHub/blob/master/docs/#L1" class="edit-link">Edit this page</a>
</div>
<div class="next-article d-print-none border-top" id="nextArticle"></div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<div class='footer-custom'><div class='footer-inner'><span class='footer-brand'>EchoHub</span><span class='footer-sep'>&middot;</span><a href='https://github.com/HueByte/EchoHub'>GitHub</a><span class='footer-sep'>&middot;</span><a href='https://echohub.voidcube.cloud'>Website</a><span class='footer-sep'>&middot;</span><span class='footer-credit'>Built with <a href='https://dotnet.github.io/docfx'>DocFX</a></span></div></div>
</div>
</div>
</footer>
</body>
</html>
+344
View File
@@ -0,0 +1,344 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Channels | EchoHub Documentation </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Channels | EchoHub Documentation ">
<link rel="icon" href="../images/hue_icon.svg">
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:rel" content="../">
<meta name="docfx:docurl" content="https://github.com/HueByte/EchoHub/blob/master/docs/#L1">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../index.html">
<img id="logo" class="svg" src="../images/hue_icon.svg" alt="EchoHub">
EchoHub
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="">
<h1 id="channels">Channels</h1>
<h2 id="channel-creation">Channel Creation</h2>
<p>Channels are created via the REST API. Public channels are broadcast to all
connected clients.</p>
<pre><code class="lang-mermaid">sequenceDiagram
participant Client as Client (TUI/API)
participant CC as ChannelsController
participant ChS as ChannelService
participant CS as ChatService
participant DB as SQLite
participant SRB as SignalRBroadcaster
participant IRCB as IrcBroadcaster
Client-&gt;&gt;CC: POST /api/channels {name, topic, isPublic}
CC-&gt;&gt;ChS: CreateChannelAsync(creatorId, name, topic, isPublic)
ChS-&gt;&gt;ChS: Normalize name (lowercase, trim)
ChS-&gt;&gt;ChS: Validate format (2-100 chars, regex)
ChS-&gt;&gt;DB: Check duplicate
ChS-&gt;&gt;DB: INSERT Channel + ChannelMembership (creator auto-added)
ChS--&gt;&gt;CC: ChannelDto
alt Channel is public
CC-&gt;&gt;CS: BroadcastChannelUpdatedAsync(channel)
CS-&gt;&gt;SRB: SendChannelUpdatedAsync(channelDto)
SRB-&gt;&gt;SRB: Notify all SignalR clients
CS-&gt;&gt;IRCB: SendChannelUpdatedAsync(channelDto)
end
CC--&gt;&gt;Client: 201 Created (ChannelDto)
</code></pre>
<p><strong>Code references:</strong></p>
<table>
<thead>
<tr>
<th>Step</th>
<th>File</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr>
<td>Controller endpoint</td>
<td><code>src/EchoHub.Server/Controllers/ChannelsController.cs</code></td>
<td>Lines 60-76</td>
</tr>
<tr>
<td>Channel service create</td>
<td><code>src/EchoHub.Server/Services/ChannelService.cs</code></td>
<td>Lines 50-90</td>
</tr>
<tr>
<td>Broadcast updated</td>
<td><code>src/EchoHub.Server/Services/ChatService.cs</code></td>
<td>Lines 308-309</td>
</tr>
</tbody>
</table>
<hr>
<h2 id="channel-deletion">Channel Deletion</h2>
<p>Only the channel creator (or admin) can delete a channel. The default channel
is protected.</p>
<pre><code class="lang-mermaid">sequenceDiagram
participant Client as Client
participant CC as ChannelsController
participant ChS as ChannelService
participant DB as SQLite
Client-&gt;&gt;CC: DELETE /api/channels/{channel}
CC-&gt;&gt;ChS: DeleteChannelAsync(channelName, callerId)
ChS-&gt;&gt;ChS: Reject if default channel
ChS-&gt;&gt;DB: Lookup channel
ChS-&gt;&gt;ChS: Verify caller is creator or admin
ChS-&gt;&gt;DB: DELETE Channel (cascade: messages, memberships)
ChS--&gt;&gt;CC: Success
CC--&gt;&gt;Client: 204 No Content
</code></pre>
<p><strong>Code references:</strong></p>
<table>
<thead>
<tr>
<th>Step</th>
<th>File</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr>
<td>Controller endpoint</td>
<td><code>src/EchoHub.Server/Controllers/ChannelsController.cs</code></td>
<td>Lines 94-106</td>
</tr>
<tr>
<td>Channel service delete</td>
<td><code>src/EchoHub.Server/Services/ChannelService.cs</code></td>
<td>Lines 119-144</td>
</tr>
</tbody>
</table>
<hr>
<h2 id="joining-a-channel">Joining a Channel</h2>
<p>Both SignalR and IRC clients join channels through <code>ChatService</code>. The presence
tracker determines if this is a genuinely new join (vs. a second connection) and
broadcasts accordingly.</p>
<pre><code class="lang-mermaid">sequenceDiagram
participant Client as Client (SignalR or IRC)
participant Entry as ChatHub / IrcCommandHandler
participant CS as ChatService
participant ChS as ChannelService
participant PT as PresenceTracker
participant DB as SQLite
participant SRB as SignalRBroadcaster
participant IRCB as IrcBroadcaster
Client-&gt;&gt;Entry: JoinChannel / JOIN #channel
Entry-&gt;&gt;CS: JoinChannelAsync(connectionId, userId, username, channel)
CS-&gt;&gt;ChS: EnsureChannelMembershipAsync(userId, channel)
ChS-&gt;&gt;DB: INSERT ChannelMembership (if not exists)
CS-&gt;&gt;PT: JoinChannel(username, channel)
PT--&gt;&gt;CS: isNewJoin?
alt First connection in this channel
CS-&gt;&gt;DB: Fetch UserPresenceDto
CS-&gt;&gt;CS: BroadcastToAllAsync(SendUserJoinedAsync)
par
CS-&gt;&gt;SRB: SendUserJoinedAsync(channel, user, excludeConn)
and
CS-&gt;&gt;IRCB: SendUserJoinedAsync(channel, user)
end
end
CS-&gt;&gt;DB: Fetch message history
CS--&gt;&gt;Entry: (history, error)
Entry--&gt;&gt;Client: History messages
</code></pre>
<p><strong>Code references:</strong></p>
<table>
<thead>
<tr>
<th>Step</th>
<th>File</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr>
<td>SignalR hub join</td>
<td><code>src/EchoHub.Server/Hubs/ChatHub.cs</code></td>
<td>Lines 59-81</td>
</tr>
<tr>
<td>IRC join</td>
<td><code>src/EchoHub.Server.Irc/IrcCommandHandler.cs</code></td>
<td>Lines 361-414</td>
</tr>
<tr>
<td>ChatService join</td>
<td><code>src/EchoHub.Server/Services/ChatService.cs</code></td>
<td>Lines 96-135</td>
</tr>
<tr>
<td>Presence join</td>
<td><code>src/EchoHub.Server/Services/PresenceTracker.cs</code></td>
<td>Lines 58-70</td>
</tr>
<tr>
<td>SignalR broadcast</td>
<td><code>src/EchoHub.Server/Services/SignalRBroadcaster.cs</code></td>
<td>Lines 26-32</td>
</tr>
<tr>
<td>IRC broadcast</td>
<td><code>src/EchoHub.Server.Irc/IrcBroadcaster.cs</code></td>
<td>Lines 34-41</td>
</tr>
</tbody>
</table>
<hr>
<h2 id="leaving-a-channel">Leaving a Channel</h2>
<pre><code class="lang-mermaid">sequenceDiagram
participant Client as Client
participant Entry as ChatHub / IrcCommandHandler
participant CS as ChatService
participant PT as PresenceTracker
participant SRB as SignalRBroadcaster
participant IRCB as IrcBroadcaster
Client-&gt;&gt;Entry: LeaveChannel / PART #channel
Entry-&gt;&gt;CS: LeaveChannelAsync(connectionId, username, channel)
CS-&gt;&gt;PT: LeaveChannel(username, channel)
CS-&gt;&gt;CS: BroadcastToAllAsync(SendUserLeftAsync)
par
CS-&gt;&gt;SRB: SendUserLeftAsync(channel, username)
and
CS-&gt;&gt;IRCB: SendUserLeftAsync(channel, username)
end
</code></pre>
<p><strong>Code references:</strong></p>
<table>
<thead>
<tr>
<th>Step</th>
<th>File</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr>
<td>SignalR hub leave</td>
<td><code>src/EchoHub.Server/Hubs/ChatHub.cs</code></td>
<td>Lines 83-96</td>
</tr>
<tr>
<td>IRC part</td>
<td><code>src/EchoHub.Server.Irc/IrcCommandHandler.cs</code></td>
<td>Lines 416-435</td>
</tr>
<tr>
<td>ChatService leave</td>
<td><code>src/EchoHub.Server/Services/ChatService.cs</code></td>
<td>Lines 137-143</td>
</tr>
<tr>
<td>Presence leave</td>
<td><code>src/EchoHub.Server/Services/PresenceTracker.cs</code></td>
<td>Lines 72-81</td>
</tr>
</tbody>
</table>
</article>
<div class="contribution d-print-none">
<a href="https://github.com/HueByte/EchoHub/blob/master/docs/#L1" class="edit-link">Edit this page</a>
</div>
<div class="next-article d-print-none border-top" id="nextArticle"></div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<div class='footer-custom'><div class='footer-inner'><span class='footer-brand'>EchoHub</span><span class='footer-sep'>&middot;</span><a href='https://github.com/HueByte/EchoHub'>GitHub</a><span class='footer-sep'>&middot;</span><a href='https://echohub.voidcube.cloud'>Website</a><span class='footer-sep'>&middot;</span><span class='footer-credit'>Built with <a href='https://dotnet.github.io/docfx'>DocFX</a></span></div></div>
</div>
</div>
</footer>
</body>
</html>
+348
View File
@@ -0,0 +1,348 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Connection | EchoHub Documentation </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Connection | EchoHub Documentation ">
<link rel="icon" href="../images/hue_icon.svg">
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:rel" content="../">
<meta name="docfx:docurl" content="https://github.com/HueByte/EchoHub/blob/master/docs/#L1">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../index.html">
<img id="logo" class="svg" src="../images/hue_icon.svg" alt="EchoHub">
EchoHub
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="">
<h1 id="connection">Connection</h1>
<h2 id="signalr-client-connection">SignalR Client Connection</h2>
<p>After authentication, the TUI client establishes a SignalR WebSocket, registers
event handlers, joins the default channel, and loads history.</p>
<pre><code class="lang-mermaid">sequenceDiagram
participant CM as ConnectionManager
participant EHC as EchoHubConnection
participant Hub as ChatHub
participant CS as ChatService
participant PT as PresenceTracker
participant DB as SQLite
CM-&gt;&gt;CM: Fetch encryption key (GET /api/server/encryption-key)
CM-&gt;&gt;EHC: new EchoHubConnection(apiClient, encryption)
EHC-&gt;&gt;EHC: Build HubConnection (URL + JWT token provider + auto-reconnect)
EHC-&gt;&gt;EHC: RegisterHandlers() — wire ReceiveMessage, UserJoined, etc.
EHC-&gt;&gt;Hub: ConnectAsync() → WebSocket handshake
Hub-&gt;&gt;CS: UserConnectedAsync(connectionId, userId, username)
CS-&gt;&gt;PT: UserConnected(connectionId, userId, username)
CS-&gt;&gt;DB: Update user: Status=Online, LastSeenAt=now
CM-&gt;&gt;CM: Fetch channel list (GET /api/channels)
CM-&gt;&gt;EHC: JoinChannelAsync(&quot;general&quot;)
EHC-&gt;&gt;Hub: InvokeAsync(&quot;JoinChannel&quot;, &quot;general&quot;)
Hub-&gt;&gt;CS: JoinChannelAsync(connectionId, userId, username, &quot;general&quot;)
CS-&gt;&gt;DB: EnsureChannelMembership
CS-&gt;&gt;PT: JoinChannel(username, &quot;general&quot;)
CS-&gt;&gt;CS: BroadcastToAllAsync → UserJoined
CS-&gt;&gt;DB: Fetch message history
Hub--&gt;&gt;EHC: List&lt;MessageDto&gt; (encrypted)
EHC--&gt;&gt;CM: Decrypted history
</code></pre>
<p><strong>Code references:</strong></p>
<table>
<thead>
<tr>
<th>Step</th>
<th>File</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr>
<td>Connection orchestration</td>
<td><code>src/EchoHub.Client/Services/ConnectionManager.cs</code></td>
<td>Lines 58-140 (<code>ConnectAsync</code>)</td>
</tr>
<tr>
<td>EchoHubConnection setup</td>
<td><code>src/EchoHub.Client/Services/EchoHubConnection.cs</code></td>
<td>Lines 29-62 (constructor)</td>
</tr>
<tr>
<td>Handler registration</td>
<td><code>src/EchoHub.Client/Services/EchoHubConnection.cs</code></td>
<td>Lines 64-122 (<code>RegisterHandlers</code>)</td>
</tr>
<tr>
<td>Hub OnConnected</td>
<td><code>src/EchoHub.Server/Hubs/ChatHub.cs</code></td>
<td>Lines 31-43</td>
</tr>
<tr>
<td>ChatService connected</td>
<td><code>src/EchoHub.Server/Services/ChatService.cs</code></td>
<td>Lines 41-57</td>
</tr>
<tr>
<td>PresenceTracker connect</td>
<td><code>src/EchoHub.Server/Services/PresenceTracker.cs</code></td>
<td>Lines 13-29</td>
</tr>
<tr>
<td>Join channel (hub)</td>
<td><code>src/EchoHub.Server/Hubs/ChatHub.cs</code></td>
<td>Lines 59-81</td>
</tr>
<tr>
<td>Join channel (service)</td>
<td><code>src/EchoHub.Server/Services/ChatService.cs</code></td>
<td>Lines 96-135</td>
</tr>
</tbody>
</table>
<hr>
<h2 id="irc-client-connection">IRC Client Connection</h2>
<p>IRC clients connect via TCP, authenticate with PASS/NICK/USER or SASL PLAIN,
and auto-join channels. New usernames are auto-registered.</p>
<pre><code class="lang-mermaid">sequenceDiagram
participant IRC as IRC Client
participant GW as IrcGatewayService
participant CH as IrcCommandHandler
participant US as UserService
participant CS as ChatService
participant PT as PresenceTracker
IRC-&gt;&gt;GW: TCP connect (:6667 or :6697 TLS)
GW-&gt;&gt;GW: Accept + create IrcClientConnection
GW-&gt;&gt;CH: new IrcCommandHandler(connection, services)
GW-&gt;&gt;CH: RunAsync() — start read loop
alt SASL PLAIN
IRC-&gt;&gt;CH: CAP REQ :sasl
CH--&gt;&gt;IRC: CAP ACK :sasl
IRC-&gt;&gt;CH: AUTHENTICATE PLAIN
CH--&gt;&gt;IRC: AUTHENTICATE +
IRC-&gt;&gt;CH: AUTHENTICATE &lt;base64(\0user\0pass)&gt;
CH-&gt;&gt;US: AuthenticateUserAsync(user, pass)
alt Auth fails → auto-register
CH-&gt;&gt;US: RegisterUserAsync(user, pass)
end
CH--&gt;&gt;IRC: 903 :SASL authentication successful
else PASS/NICK/USER
IRC-&gt;&gt;CH: PASS &lt;password&gt;
IRC-&gt;&gt;CH: NICK &lt;nickname&gt;
IRC-&gt;&gt;CH: USER &lt;username&gt; 0 * :&lt;realname&gt;
CH-&gt;&gt;US: AuthenticateUserAsync(nick, pass)
alt Auth fails → auto-register
CH-&gt;&gt;US: RegisterUserAsync(nick, pass)
end
end
CH-&gt;&gt;CS: UserConnectedAsync(irc-{guid}, userId, username)
CS-&gt;&gt;PT: UserConnected(irc-{guid}, userId, username)
CH--&gt;&gt;IRC: 001-004 RPL_WELCOME burst + MOTD
Note over IRC,CH: Client is now ready for JOIN/PART/PRIVMSG
</code></pre>
<p><strong>Code references:</strong></p>
<table>
<thead>
<tr>
<th>Step</th>
<th>File</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr>
<td>TCP listener</td>
<td><code>src/EchoHub.Server.Irc/IrcGatewayService.cs</code></td>
<td>Lines 45-90 (<code>ExecuteAsync</code>)</td>
</tr>
<tr>
<td>Client handler</td>
<td><code>src/EchoHub.Server.Irc/IrcGatewayService.cs</code></td>
<td>Lines 92-154 (<code>HandleClientAsync</code>)</td>
</tr>
<tr>
<td>Command read loop</td>
<td><code>src/EchoHub.Server.Irc/IrcCommandHandler.cs</code></td>
<td>Lines 40-98 (<code>RunAsync</code>)</td>
</tr>
<tr>
<td>SASL auth</td>
<td><code>src/EchoHub.Server.Irc/IrcCommandHandler.cs</code></td>
<td>Lines 136-207 (<code>HandleAuthenticateAsync</code>)</td>
</tr>
<tr>
<td>PASS/NICK/USER</td>
<td><code>src/EchoHub.Server.Irc/IrcCommandHandler.cs</code></td>
<td>Lines 209-267</td>
</tr>
<tr>
<td>Registration completion</td>
<td><code>src/EchoHub.Server.Irc/IrcCommandHandler.cs</code></td>
<td>Lines 268-315 (<code>TryCompleteRegistrationAsync</code>)</td>
</tr>
<tr>
<td>Cleanup on disconnect</td>
<td><code>src/EchoHub.Server.Irc/IrcGatewayService.cs</code></td>
<td>Lines 136-153</td>
</tr>
</tbody>
</table>
<hr>
<h2 id="user-disconnect--presence">User Disconnect &amp; Presence</h2>
<p>When a client disconnects, the presence tracker determines if the user has any
remaining connections. If not, status is set to Invisible and all channels are
notified.</p>
<pre><code class="lang-mermaid">sequenceDiagram
participant Client as Client
participant Entry as ChatHub / IrcGatewayService
participant CS as ChatService
participant PT as PresenceTracker
participant DB as SQLite
participant SRB as SignalRBroadcaster
Client-&gt;&gt;Entry: Disconnect / TCP close
Entry-&gt;&gt;CS: UserDisconnectedAsync(connectionId)
CS-&gt;&gt;PT: Get username + channels (before removal)
CS-&gt;&gt;PT: UserDisconnected(connectionId)
PT-&gt;&gt;PT: Remove connection from tracking
alt No remaining connections for user
CS-&gt;&gt;DB: Update user: Status=Invisible, LastSeenAt=now
loop For each channel user was in
CS-&gt;&gt;CS: BroadcastToAllAsync(SendUserStatusChangedAsync)
CS-&gt;&gt;SRB: Notify channel members
end
end
</code></pre>
<p><strong>Code references:</strong></p>
<table>
<thead>
<tr>
<th>Step</th>
<th>File</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr>
<td>SignalR disconnect</td>
<td><code>src/EchoHub.Server/Hubs/ChatHub.cs</code></td>
<td>Lines 45-57</td>
</tr>
<tr>
<td>IRC cleanup</td>
<td><code>src/EchoHub.Server.Irc/IrcGatewayService.cs</code></td>
<td>Lines 136-153</td>
</tr>
<tr>
<td>ChatService disconnect</td>
<td><code>src/EchoHub.Server/Services/ChatService.cs</code></td>
<td>Lines 59-94</td>
</tr>
<tr>
<td>Presence disconnect</td>
<td><code>src/EchoHub.Server/Services/PresenceTracker.cs</code></td>
<td>Lines 31-53</td>
</tr>
</tbody>
</table>
</article>
<div class="contribution d-print-none">
<a href="https://github.com/HueByte/EchoHub/blob/master/docs/#L1" class="edit-link">Edit this page</a>
</div>
<div class="next-article d-print-none border-top" id="nextArticle"></div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<div class='footer-custom'><div class='footer-inner'><span class='footer-brand'>EchoHub</span><span class='footer-sep'>&middot;</span><a href='https://github.com/HueByte/EchoHub'>GitHub</a><span class='footer-sep'>&middot;</span><a href='https://echohub.voidcube.cloud'>Website</a><span class='footer-sep'>&middot;</span><span class='footer-credit'>Built with <a href='https://dotnet.github.io/docfx'>DocFX</a></span></div></div>
</div>
</div>
</footer>
</body>
</html>
+117
View File
@@ -0,0 +1,117 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Flows | EchoHub Documentation </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Flows | EchoHub Documentation ">
<link rel="icon" href="../images/hue_icon.svg">
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:rel" content="../">
<meta name="docfx:docurl" content="https://github.com/HueByte/EchoHub/blob/master/docs/#L1">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../index.html">
<img id="logo" class="svg" src="../images/hue_icon.svg" alt="EchoHub">
EchoHub
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="">
<h1 id="flows">Flows</h1>
<p>This section documents the major request/event flows in EchoHub, showing how data moves between the TUI client, IRC client, server, and database. Each diagram includes code references so you can jump straight to the implementation.</p>
</article>
<div class="contribution d-print-none">
<a href="https://github.com/HueByte/EchoHub/blob/master/docs/#L1" class="edit-link">Edit this page</a>
</div>
<div class="next-article d-print-none border-top" id="nextArticle"></div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<div class='footer-custom'><div class='footer-inner'><span class='footer-brand'>EchoHub</span><span class='footer-sep'>&middot;</span><a href='https://github.com/HueByte/EchoHub'>GitHub</a><span class='footer-sep'>&middot;</span><a href='https://echohub.voidcube.cloud'>Website</a><span class='footer-sep'>&middot;</span><span class='footer-credit'>Built with <a href='https://dotnet.github.io/docfx'>DocFX</a></span></div></div>
</div>
</div>
</footer>
</body>
</html>
+296
View File
@@ -0,0 +1,296 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Media &amp; Services | EchoHub Documentation </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Media &amp; Services | EchoHub Documentation ">
<link rel="icon" href="../images/hue_icon.svg">
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:rel" content="../">
<meta name="docfx:docurl" content="https://github.com/HueByte/EchoHub/blob/master/docs/#L1">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../index.html">
<img id="logo" class="svg" src="../images/hue_icon.svg" alt="EchoHub">
EchoHub
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="">
<h1 id="media--services">Media &amp; Services</h1>
<h2 id="file-upload">File Upload</h2>
<p>Files are uploaded via REST, validated by magic bytes, stored with GUID filenames,
and broadcast as a message with a download link.</p>
<pre><code class="lang-mermaid">sequenceDiagram
participant Client as Client
participant CC as ChannelsController
participant FV as FileValidationHelper
participant FS as FileStorageService
participant CS as ChatService
participant DB as SQLite
Client-&gt;&gt;CC: POST /api/channels/{channel}/upload (multipart)
CC-&gt;&gt;CC: Check file size limits
CC-&gt;&gt;FV: IsValidImage(stream) — magic byte check
FV-&gt;&gt;FV: Read header: JPEG(FFD8FF) / PNG(89504E47) / GIF / WebP(RIFF+WEBP)
FV--&gt;&gt;CC: true/false
CC-&gt;&gt;FS: SaveFileAsync(stream, extension)
FS-&gt;&gt;FS: Generate GUID filename, write to uploads/
FS--&gt;&gt;CC: fileId (GUID)
CC-&gt;&gt;CC: Determine MessageType (Image/Audio/File)
CC-&gt;&gt;CS: SendMessageAsync (with file URL + optional ASCII art)
CS-&gt;&gt;DB: INSERT Message
CS-&gt;&gt;CS: BroadcastToAllAsync → fan out to clients
</code></pre>
<p><strong>Code references:</strong></p>
<table>
<thead>
<tr>
<th>Step</th>
<th>File</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr>
<td>Upload endpoint</td>
<td><code>src/EchoHub.Server/Controllers/ChannelsController.cs</code></td>
<td>Lines 108-200</td>
</tr>
<tr>
<td>File validation</td>
<td><code>src/EchoHub.Server/Services/FileValidationHelper.cs</code></td>
<td>Lines 15-82</td>
</tr>
<tr>
<td>File storage</td>
<td><code>src/EchoHub.Server/Services/FileStorageService.cs</code></td>
<td>Lines 1-47</td>
</tr>
<tr>
<td>File download</td>
<td><code>src/EchoHub.Server/Controllers/FilesController.cs</code></td>
<td>Lines 22-53</td>
</tr>
</tbody>
</table>
<hr>
<h2 id="link-embed-resolution">Link Embed Resolution</h2>
<p>When a message contains URLs, the server fetches OpenGraph metadata for preview
embeds.</p>
<pre><code class="lang-mermaid">sequenceDiagram
participant CS as ChatService
participant LE as LinkEmbedService
participant Web as External Website
CS-&gt;&gt;LE: TryGetEmbedsAsync(messageContent)
LE-&gt;&gt;LE: Extract URLs via regex
LE-&gt;&gt;LE: Filter: max URLs per message, skip duplicates
loop For each URL
LE-&gt;&gt;LE: Validate: http(s) only, block private IPs
LE-&gt;&gt;Web: GET URL (timeout + size limit)
Web--&gt;&gt;LE: HTML response
LE-&gt;&gt;LE: Parse og:title, og:description, og:site_name
LE-&gt;&gt;LE: Parse theme-color meta tag
LE-&gt;&gt;LE: Fallback to &lt;title&gt; if no og:title
end
LE--&gt;&gt;CS: List&lt;EmbedDto&gt; (or null)
Note over CS: Attached to MessageDto before broadcast
</code></pre>
<p><strong>Code references:</strong></p>
<table>
<thead>
<tr>
<th>Step</th>
<th>File</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr>
<td>Entry point</td>
<td><code>src/EchoHub.Server/Services/LinkEmbedService.cs</code></td>
<td>Lines 28-51 (<code>TryGetEmbedsAsync</code>)</td>
</tr>
<tr>
<td>URL extraction</td>
<td><code>src/EchoHub.Server/Services/LinkEmbedService.cs</code></td>
<td>Lines 145-160</td>
</tr>
<tr>
<td>Private IP blocking</td>
<td><code>src/EchoHub.Server/Services/LinkEmbedService.cs</code></td>
<td>Lines 162-181</td>
</tr>
<tr>
<td>OG tag parsing</td>
<td><code>src/EchoHub.Server/Services/LinkEmbedService.cs</code></td>
<td>Lines 187-210</td>
</tr>
<tr>
<td>Theme color parsing</td>
<td><code>src/EchoHub.Server/Services/LinkEmbedService.cs</code></td>
<td>Lines 117-143</td>
</tr>
<tr>
<td>ChatService integration</td>
<td><code>src/EchoHub.Server/Services/ChatService.cs</code></td>
<td>Lines 194-201</td>
</tr>
</tbody>
</table>
<hr>
<h2 id="server-directory-registration">Server Directory Registration</h2>
<p>Public servers register with the EchoHubSpace directory for discoverability.</p>
<pre><code class="lang-mermaid">sequenceDiagram
participant SDS as ServerDirectoryService
participant Dir as EchoHubSpace Directory
participant PT as PresenceTracker
SDS-&gt;&gt;SDS: Check Server:PublicServer config
SDS-&gt;&gt;Dir: SignalR connect (echohub.voidcube.cloud/hubs/servers)
SDS-&gt;&gt;Dir: RegisterServer(name, description, host, userCount)
Dir--&gt;&gt;SDS: Registered
loop Every 30 seconds
SDS-&gt;&gt;PT: Get online user count
alt Count changed
SDS-&gt;&gt;Dir: UpdateUserCount(count)
end
end
Dir-&gt;&gt;SDS: Ping
SDS-&gt;&gt;Dir: Heartbeat
Note over SDS,Dir: Exponential backoff on disconnect (2s → 30s max)
</code></pre>
<p><strong>Code references:</strong></p>
<table>
<thead>
<tr>
<th>Step</th>
<th>File</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr>
<td>Service lifecycle</td>
<td><code>src/EchoHub.Server/Services/ServerDirectoryService.cs</code></td>
<td>Lines 29-122</td>
</tr>
<tr>
<td>Registration</td>
<td><code>src/EchoHub.Server/Services/ServerDirectoryService.cs</code></td>
<td>Lines 195-212</td>
</tr>
<tr>
<td>User count polling</td>
<td><code>src/EchoHub.Server/Services/ServerDirectoryService.cs</code></td>
<td>Lines 154-187</td>
</tr>
<tr>
<td>Reconnection backoff</td>
<td><code>src/EchoHub.Server/Services/ServerDirectoryService.cs</code></td>
<td>Lines 77-82, 191</td>
</tr>
</tbody>
</table>
</article>
<div class="contribution d-print-none">
<a href="https://github.com/HueByte/EchoHub/blob/master/docs/#L1" class="edit-link">Edit this page</a>
</div>
<div class="next-article d-print-none border-top" id="nextArticle"></div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<div class='footer-custom'><div class='footer-inner'><span class='footer-brand'>EchoHub</span><span class='footer-sep'>&middot;</span><a href='https://github.com/HueByte/EchoHub'>GitHub</a><span class='footer-sep'>&middot;</span><a href='https://echohub.voidcube.cloud'>Website</a><span class='footer-sep'>&middot;</span><span class='footer-credit'>Built with <a href='https://dotnet.github.io/docfx'>DocFX</a></span></div></div>
</div>
</div>
</footer>
</body>
</html>
+513
View File
@@ -0,0 +1,513 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Messaging | EchoHub Documentation </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Messaging | EchoHub Documentation ">
<link rel="icon" href="../images/hue_icon.svg">
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:rel" content="../">
<meta name="docfx:docurl" content="https://github.com/HueByte/EchoHub/blob/master/docs/#L1">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../index.html">
<img id="logo" class="svg" src="../images/hue_icon.svg" alt="EchoHub">
EchoHub
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="">
<h1 id="messaging">Messaging</h1>
<h2 id="sending-a-message-signalr">Sending a Message (SignalR)</h2>
<p>A message typed in the TUI travels through encryption, the SignalR hub,
<code>ChatService</code> validation, database storage, and fan-out to both SignalR and IRC
clients.</p>
<pre><code class="lang-mermaid">sequenceDiagram
participant UI as MainWindow (TUI)
participant AO as AppOrchestrator
participant EHC as EchoHubConnection
participant Hub as ChatHub
participant CS as ChatService
participant LE as LinkEmbedService
participant DB as SQLite
participant SRB as SignalRBroadcaster
participant IRCB as IrcBroadcaster
participant Clients as Other Clients
UI-&gt;&gt;AO: OnMessageSubmitted(channel, text)
AO-&gt;&gt;AO: IsCommand(text)? → No
AO-&gt;&gt;EHC: SendMessageAsync(channel, text)
EHC-&gt;&gt;EHC: Encrypt(text) → ciphertext
EHC-&gt;&gt;Hub: InvokeAsync(&quot;SendMessage&quot;, channel, ciphertext)
Hub-&gt;&gt;CS: SendMessageAsync(userId, username, channel, ciphertext)
CS-&gt;&gt;CS: Decrypt(ciphertext) → plaintext
CS-&gt;&gt;CS: Validate (length, newlines, channel exists)
CS-&gt;&gt;DB: Check mute status
CS-&gt;&gt;LE: TryGetEmbedsAsync(plaintext)
LE-&gt;&gt;LE: Extract URLs, fetch OG tags
LE--&gt;&gt;CS: List&lt;EmbedDto&gt; (or null)
CS-&gt;&gt;DB: INSERT Message (encrypted at rest)
CS-&gt;&gt;CS: Re-encrypt plaintext for transport
CS-&gt;&gt;CS: Build MessageDto with embeds
par Fan-out to all broadcasters
CS-&gt;&gt;SRB: SendMessageToChannelAsync(channel, dto)
SRB-&gt;&gt;Clients: HubContext.Group(channel).ReceiveMessage(dto)
and
CS-&gt;&gt;IRCB: SendMessageToChannelAsync(channel, dto)
IRCB-&gt;&gt;IRCB: Decrypt → format as PRIVMSG lines
IRCB-&gt;&gt;Clients: Send to each IRC conn (skip sender)
end
</code></pre>
<p><strong>Code references:</strong></p>
<table>
<thead>
<tr>
<th>Step</th>
<th>File</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr>
<td>Input handler</td>
<td><code>src/EchoHub.Client/UI/MainWindow.cs</code></td>
<td>Lines 428-449 (<code>OnInputKeyDown</code>)</td>
</tr>
<tr>
<td>Orchestrator dispatch</td>
<td><code>src/EchoHub.Client/AppOrchestrator.cs</code></td>
<td>Lines 631-661 (<code>HandleMessageSubmitted</code>)</td>
</tr>
<tr>
<td>Client encrypt + send</td>
<td><code>src/EchoHub.Client/Services/EchoHubConnection.cs</code></td>
<td>Lines 148-153 (<code>SendMessageAsync</code>)</td>
</tr>
<tr>
<td>Hub receive</td>
<td><code>src/EchoHub.Server/Hubs/ChatHub.cs</code></td>
<td>Lines 98-111 (<code>SendMessage</code>)</td>
</tr>
<tr>
<td>ChatService process</td>
<td><code>src/EchoHub.Server/Services/ChatService.cs</code></td>
<td>Lines 145-241 (<code>SendMessageAsync</code>)</td>
</tr>
<tr>
<td>Mute check</td>
<td><code>src/EchoHub.Server/Services/ChatService.cs</code></td>
<td>Lines 177-190</td>
</tr>
<tr>
<td>Link embeds</td>
<td><code>src/EchoHub.Server/Services/LinkEmbedService.cs</code></td>
<td>Lines 28-51 (<code>TryGetEmbedsAsync</code>)</td>
</tr>
<tr>
<td>DB insert</td>
<td><code>src/EchoHub.Server/Services/ChatService.cs</code></td>
<td>Lines 208-221</td>
</tr>
<tr>
<td>Broadcast fan-out</td>
<td><code>src/EchoHub.Server/Services/ChatService.cs</code></td>
<td>Lines 311-324 (<code>BroadcastToAllAsync</code>)</td>
</tr>
<tr>
<td>SignalR broadcast</td>
<td><code>src/EchoHub.Server/Services/SignalRBroadcaster.cs</code></td>
<td>Lines 23-24</td>
</tr>
<tr>
<td>IRC broadcast</td>
<td><code>src/EchoHub.Server.Irc/IrcBroadcaster.cs</code></td>
<td>Lines 17-32</td>
</tr>
</tbody>
</table>
<hr>
<h2 id="sending-a-message-irc">Sending a Message (IRC)</h2>
<p>Messages from IRC clients follow the same <code>ChatService</code> path but enter as
plaintext (no app-layer encryption).</p>
<pre><code class="lang-mermaid">sequenceDiagram
participant IRC as IRC Client
participant CH as IrcCommandHandler
participant CS as ChatService
participant DB as SQLite
participant SRB as SignalRBroadcaster
participant IRCB as IrcBroadcaster
IRC-&gt;&gt;CH: PRIVMSG #channel :Hello world
CH-&gt;&gt;CH: Parse target + content
CH-&gt;&gt;CH: IrcToEchoHubChannel(&quot;#channel&quot;) → &quot;channel&quot;
CH-&gt;&gt;CS: SendMessageAsync(userId, username, &quot;channel&quot;, &quot;Hello world&quot;)
CS-&gt;&gt;CS: Decrypt(&quot;Hello world&quot;) → passthrough (no $ENC$ prefix)
CS-&gt;&gt;CS: Validate, check mute, fetch embeds
CS-&gt;&gt;DB: INSERT Message
CS-&gt;&gt;CS: Encrypt plaintext for SignalR transport
par Fan-out
CS-&gt;&gt;SRB: SendMessageToChannelAsync (encrypted for SignalR)
and
CS-&gt;&gt;IRCB: SendMessageToChannelAsync (decrypt → PRIVMSG)
IRCB-&gt;&gt;IRCB: Skip sender (IRC echo suppression)
end
</code></pre>
<p><strong>Code references:</strong></p>
<table>
<thead>
<tr>
<th>Step</th>
<th>File</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr>
<td>PRIVMSG handler</td>
<td><code>src/EchoHub.Server.Irc/IrcCommandHandler.cs</code></td>
<td>Lines 437-469</td>
</tr>
<tr>
<td>Channel name conversion</td>
<td><code>src/EchoHub.Server.Irc/IrcCommandHandler.cs</code></td>
<td>Line 680 (<code>IrcToEchoHubChannel</code>)</td>
</tr>
<tr>
<td>ChatService (shared path)</td>
<td><code>src/EchoHub.Server/Services/ChatService.cs</code></td>
<td>Lines 145-241</td>
</tr>
<tr>
<td>IRC echo suppression</td>
<td><code>src/EchoHub.Server.Irc/IrcBroadcaster.cs</code></td>
<td>Lines 25-26</td>
</tr>
</tbody>
</table>
<hr>
<h2 id="receiving-a-message-tui-client">Receiving a Message (TUI Client)</h2>
<p>When a message arrives via SignalR, the client decrypts it, adds it to the chat
view, and optionally plays a notification sound for @mentions.</p>
<pre><code class="lang-mermaid">sequenceDiagram
participant SRB as SignalRBroadcaster
participant EHC as EchoHubConnection
participant AO as AppOrchestrator
participant MM as ChatMessageManager
participant UI as MainWindow
SRB-&gt;&gt;EHC: ReceiveMessage(MessageDto)
EHC-&gt;&gt;EHC: Decrypt(message.Content)
EHC--&gt;&gt;AO: OnMessageReceived(decrypted dto)
AO-&gt;&gt;AO: InvokeUI (thread-safe)
AO-&gt;&gt;MM: AddMessage(message)
MM-&gt;&gt;UI: Render in chat ListView
alt Message contains @username
AO-&gt;&gt;AO: PlayAsync() notification sound
end
</code></pre>
<p><strong>Code references:</strong></p>
<table>
<thead>
<tr>
<th>Step</th>
<th>File</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr>
<td>SignalR handler</td>
<td><code>src/EchoHub.Client/Services/EchoHubConnection.cs</code></td>
<td>Lines 64-71</td>
</tr>
<tr>
<td>Orchestrator receive</td>
<td><code>src/EchoHub.Client/AppOrchestrator.cs</code></td>
<td>Lines 372-383</td>
</tr>
<tr>
<td>@mention detection</td>
<td><code>src/EchoHub.Client/AppOrchestrator.cs</code></td>
<td>Lines 378-382</td>
</tr>
</tbody>
</table>
<hr>
<h2 id="command-execution">Command Execution</h2>
<p>Slash commands (<code>/status</code>, <code>/nick</code>, <code>/kick</code>, etc.) are parsed client-side and
dispatched to appropriate handlers, which call REST APIs or SignalR methods.</p>
<pre><code class="lang-mermaid">sequenceDiagram
participant UI as MainWindow
participant AO as AppOrchestrator
participant CMD as CommandHandler
participant API as ApiClient
participant EHC as EchoHubConnection
participant Server as Server (API/Hub)
UI-&gt;&gt;AO: OnMessageSubmitted(channel, &quot;/kick baduser&quot;)
AO-&gt;&gt;CMD: IsCommand(&quot;/kick baduser&quot;)? → true
AO-&gt;&gt;CMD: HandleAsync(&quot;/kick baduser&quot;)
CMD-&gt;&gt;CMD: Parse → command=&quot;kick&quot;, args=&quot;baduser&quot;
alt API command (kick, ban, mute, nick, etc.)
CMD--&gt;&gt;AO: Fire OnKickRequested(&quot;baduser&quot;)
AO-&gt;&gt;API: KickUserAsync(&quot;baduser&quot;)
API-&gt;&gt;Server: POST /api/moderation/kick/baduser
else Hub command (status, join, leave, etc.)
CMD--&gt;&gt;AO: Fire OnSetStatus / OnJoinChannel / etc.
AO-&gt;&gt;EHC: UpdateStatusAsync() / JoinChannelAsync() / etc.
EHC-&gt;&gt;Server: SignalR Invoke
else Local command (theme, help, quit)
CMD--&gt;&gt;AO: Fire OnThemeChanged / etc.
AO-&gt;&gt;UI: Apply locally (no server call)
end
AO-&gt;&gt;UI: AddSystemMessage(result)
</code></pre>
<p><strong>Available commands:</strong></p>
<table>
<thead>
<tr>
<th>Command</th>
<th>Type</th>
<th>Handler</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>/status &lt;status&gt; [message]</code></td>
<td>Hub</td>
<td><code>UpdateStatusAsync</code></td>
</tr>
<tr>
<td><code>/nick &lt;name&gt;</code></td>
<td>API</td>
<td><code>UpdateProfileAsync</code></td>
</tr>
<tr>
<td><code>/color &lt;hex&gt;</code></td>
<td>API</td>
<td><code>UpdateProfileAsync</code></td>
</tr>
<tr>
<td><code>/join &lt;channel&gt;</code></td>
<td>Hub</td>
<td><code>JoinChannelAsync</code></td>
</tr>
<tr>
<td><code>/leave</code></td>
<td>Hub</td>
<td><code>LeaveChannelAsync</code></td>
</tr>
<tr>
<td><code>/topic &lt;text&gt;</code></td>
<td>API</td>
<td><code>UpdateChannelTopicAsync</code></td>
</tr>
<tr>
<td><code>/kick &lt;user&gt;</code></td>
<td>API</td>
<td><code>POST /api/moderation/kick/{user}</code></td>
</tr>
<tr>
<td><code>/ban &lt;user&gt;</code></td>
<td>API</td>
<td><code>POST /api/moderation/ban/{user}</code></td>
</tr>
<tr>
<td><code>/unban &lt;user&gt;</code></td>
<td>API</td>
<td><code>POST /api/moderation/unban/{user}</code></td>
</tr>
<tr>
<td><code>/mute &lt;user&gt; [mins]</code></td>
<td>API</td>
<td><code>POST /api/moderation/mute/{user}</code></td>
</tr>
<tr>
<td><code>/unmute &lt;user&gt;</code></td>
<td>API</td>
<td><code>POST /api/moderation/unmute/{user}</code></td>
</tr>
<tr>
<td><code>/role &lt;user&gt; &lt;role&gt;</code></td>
<td>API</td>
<td><code>PUT /api/moderation/role/{user}</code></td>
</tr>
<tr>
<td><code>/nuke</code></td>
<td>API</td>
<td><code>DELETE /api/channels/{channel}/messages</code></td>
</tr>
<tr>
<td><code>/send &lt;file&gt;</code></td>
<td>API</td>
<td><code>POST /api/channels/{channel}/upload</code></td>
</tr>
<tr>
<td><code>/profile [user]</code></td>
<td>Local</td>
<td>Show profile dialog</td>
</tr>
<tr>
<td><code>/avatar</code></td>
<td>API</td>
<td><code>POST /api/users/avatar</code></td>
</tr>
<tr>
<td><code>/theme &lt;name&gt;</code></td>
<td>Local</td>
<td><code>ThemeManager.SetTheme()</code></td>
</tr>
<tr>
<td><code>/servers</code></td>
<td>API</td>
<td><code>GET /api/serverdir/servers</code></td>
</tr>
<tr>
<td><code>/users</code></td>
<td>Local</td>
<td>Show userlist</td>
</tr>
<tr>
<td><code>/help</code></td>
<td>Local</td>
<td>Show help text</td>
</tr>
<tr>
<td><code>/quit</code></td>
<td>Local</td>
<td>Exit application</td>
</tr>
</tbody>
</table>
<p><strong>Code references:</strong></p>
<table>
<thead>
<tr>
<th>Step</th>
<th>File</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr>
<td>Command detection</td>
<td><code>src/EchoHub.Client/AppOrchestrator.cs</code></td>
<td>Lines 639-655</td>
</tr>
<tr>
<td>Command dispatch</td>
<td><code>src/EchoHub.Client/Commands/CommandHandler.cs</code></td>
<td>Lines 34-69 (<code>HandleAsync</code>)</td>
</tr>
<tr>
<td>Command handlers wired</td>
<td><code>src/EchoHub.Client/AppOrchestrator.cs</code></td>
<td>Lines 97-117</td>
</tr>
<tr>
<td>Individual handlers</td>
<td><code>src/EchoHub.Client/AppOrchestrator.cs</code></td>
<td>Lines 122-350</td>
</tr>
</tbody>
</table>
</article>
<div class="contribution d-print-none">
<a href="https://github.com/HueByte/EchoHub/blob/master/docs/#L1" class="edit-link">Edit this page</a>
</div>
<div class="next-article d-print-none border-top" id="nextArticle"></div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<div class='footer-custom'><div class='footer-inner'><span class='footer-brand'>EchoHub</span><span class='footer-sep'>&middot;</span><a href='https://github.com/HueByte/EchoHub'>GitHub</a><span class='footer-sep'>&middot;</span><a href='https://echohub.voidcube.cloud'>Website</a><span class='footer-sep'>&middot;</span><span class='footer-credit'>Built with <a href='https://dotnet.github.io/docfx'>DocFX</a></span></div></div>
</div>
</div>
</footer>
</body>
</html>
+196
View File
@@ -0,0 +1,196 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Moderation | EchoHub Documentation </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Moderation | EchoHub Documentation ">
<link rel="icon" href="../images/hue_icon.svg">
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:rel" content="../">
<meta name="docfx:docurl" content="https://github.com/HueByte/EchoHub/blob/master/docs/#L1">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../index.html">
<img id="logo" class="svg" src="../images/hue_icon.svg" alt="EchoHub">
EchoHub
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="">
<h1 id="moderation">Moderation</h1>
<h2 id="kick--ban--mute">Kick / Ban / Mute</h2>
<p>Moderators and admins can kick, ban, or mute users via REST API or slash commands.
These actions force-disconnect the target and broadcast the event.</p>
<pre><code class="lang-mermaid">sequenceDiagram
participant Mod as Moderator
participant MC as ModerationController
participant CS as ChatService
participant PT as PresenceTracker
participant DB as SQLite
participant SRB as SignalRBroadcaster
participant IRCB as IrcBroadcaster
Mod-&gt;&gt;MC: POST /api/moderation/kick/{user}
alt Kick
MC-&gt;&gt;CS: Get user's channels
MC-&gt;&gt;CS: BroadcastToAllAsync(SendUserKickedAsync)
MC-&gt;&gt;CS: ForceDisconnectAndCleanupAsync(user)
else Ban
MC-&gt;&gt;DB: Set user.IsBanned = true
MC-&gt;&gt;CS: BroadcastToAllAsync(SendUserBannedAsync)
MC-&gt;&gt;CS: ForceDisconnectAndCleanupAsync(user)
else Mute
MC-&gt;&gt;DB: Set user.IsMuted = true, MutedUntil = now + duration
Note over DB: MuteExpirationService auto-unmutes when timer expires
end
CS-&gt;&gt;PT: ForceRemoveUser(username)
PT-&gt;&gt;PT: Remove from all connections + channels
CS-&gt;&gt;SRB: ForceDisconnectUserAsync(connectionIds, reason)
CS-&gt;&gt;IRCB: ForceDisconnectUserAsync(connectionIds, reason)
CS-&gt;&gt;DB: Set Status=Invisible, LastSeenAt=now
</code></pre>
<p><strong>Code references:</strong></p>
<table>
<thead>
<tr>
<th>Step</th>
<th>File</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr>
<td>Kick endpoint</td>
<td><code>src/EchoHub.Server/Controllers/ModerationController.cs</code></td>
<td>Lines 62-87</td>
</tr>
<tr>
<td>Ban endpoint</td>
<td><code>src/EchoHub.Server/Controllers/ModerationController.cs</code></td>
<td>Lines 89-112</td>
</tr>
<tr>
<td>Mute endpoint</td>
<td><code>src/EchoHub.Server/Controllers/ModerationController.cs</code></td>
<td>Lines 130-151</td>
</tr>
<tr>
<td>Force disconnect</td>
<td><code>src/EchoHub.Server/Controllers/ModerationController.cs</code></td>
<td>Lines 232-256</td>
</tr>
<tr>
<td>Mute expiration</td>
<td><code>src/EchoHub.Server/Services/MuteExpirationService.cs</code></td>
<td>Lines 22-62</td>
</tr>
<tr>
<td>Mute enforcement</td>
<td><code>src/EchoHub.Server/Services/ChatService.cs</code></td>
<td>Lines 177-190</td>
</tr>
<tr>
<td>Presence force remove</td>
<td><code>src/EchoHub.Server/Services/PresenceTracker.cs</code></td>
<td>Lines 161-178</td>
</tr>
</tbody>
</table>
</article>
<div class="contribution d-print-none">
<a href="https://github.com/HueByte/EchoHub/blob/master/docs/#L1" class="edit-link">Edit this page</a>
</div>
<div class="next-article d-print-none border-top" id="nextArticle"></div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<div class='footer-custom'><div class='footer-inner'><span class='footer-brand'>EchoHub</span><span class='footer-sep'>&middot;</span><a href='https://github.com/HueByte/EchoHub'>GitHub</a><span class='footer-sep'>&middot;</span><a href='https://echohub.voidcube.cloud'>Website</a><span class='footer-sep'>&middot;</span><span class='footer-credit'>Built with <a href='https://dotnet.github.io/docfx'>DocFX</a></span></div></div>
</div>
</div>
</footer>
</body>
</html>
+37
View File
@@ -0,0 +1,37 @@
<div id="sidetoggle">
<div>
<div class="sidefilter">
<form class="toc-filter">
<span class="glyphicon glyphicon-filter filter-icon"></span>
<span class="glyphicon glyphicon-remove clear-icon" id="toc_filter_clear"></span>
<input type="text" id="toc_filter_input" placeholder="Filter by title" onkeypress="if(event.keyCode==13) {return false;}">
</form>
</div>
<div class="sidetoc">
<div class="toc" id="toc">
<ul class="nav level1">
<li>
<a href="authentication.html" name="" title="Authentication">Authentication</a>
</li>
<li>
<a href="connection.html" name="" title="Connection">Connection</a>
</li>
<li>
<a href="messaging.html" name="" title="Messaging">Messaging</a>
</li>
<li>
<a href="channels.html" name="" title="Channels">Channels</a>
</li>
<li>
<a href="moderation.html" name="" title="Moderation">Moderation</a>
</li>
<li>
<a href="media.html" name="" title="Media &amp; Services">Media &amp; Services</a>
</li>
</ul>
</div>
</div>
</div>
</div>
+2
View File
@@ -0,0 +1,2 @@
{"items":[{"name":"Authentication","href":"authentication.html","topicHref":"authentication.html"},{"name":"Connection","href":"connection.html","topicHref":"connection.html"},{"name":"Messaging","href":"messaging.html","topicHref":"messaging.html"},{"name":"Channels","href":"channels.html","topicHref":"channels.html"},{"name":"Moderation","href":"moderation.html","topicHref":"moderation.html"},{"name":"Media & Services","href":"media.html","topicHref":"media.html"}]}
+119 -24
View File
File diff suppressed because one or more lines are too long
+239
View File
@@ -192,6 +192,20 @@
"Title": "EchoHub.Client.Services.AudioPlaybackService",
"Summary": null
},
{
"type": "ManagedReference",
"source_relative_path": "_api_meta/client/EchoHub.Client.Services.BackupInfo.yml",
"output": {
".html": {
"relative_path": "api/client/EchoHub.Client.Services.BackupInfo.html"
}
},
"version": "",
"Uid": null,
"IsMRef": true,
"Title": "EchoHub.Client.Services.BackupInfo",
"Summary": null
},
{
"type": "ManagedReference",
"source_relative_path": "_api_meta/client/EchoHub.Client.Services.ClientEncryptionService.yml",
@@ -234,6 +248,34 @@
"Title": "EchoHub.Client.Services.NotificationSoundService",
"Summary": null
},
{
"type": "ManagedReference",
"source_relative_path": "_api_meta/client/EchoHub.Client.Services.PathSetup.yml",
"output": {
".html": {
"relative_path": "api/client/EchoHub.Client.Services.PathSetup.html"
}
},
"version": "",
"Uid": null,
"IsMRef": true,
"Title": "EchoHub.Client.Services.PathSetup",
"Summary": "<p sourcefile=\"_api_meta/client/EchoHub.Client.Services.PathSetup.yml\" sourcestartlinenumber=\"1\">Ensures the application's directory is on the system PATH so users\ncan run 'echohub' from any terminal session.</p>\n"
},
{
"type": "ManagedReference",
"source_relative_path": "_api_meta/client/EchoHub.Client.Services.UpdateBackupService.yml",
"output": {
".html": {
"relative_path": "api/client/EchoHub.Client.Services.UpdateBackupService.html"
}
},
"version": "",
"Uid": null,
"IsMRef": true,
"Title": "EchoHub.Client.Services.UpdateBackupService",
"Summary": "<p sourcefile=\"_api_meta/client/EchoHub.Client.Services.UpdateBackupService.yml\" sourcestartlinenumber=\"1\">Manages pre-update backups and rollback restoration for the auto-updater.\nBackup location: ~/.echohub/update-backup/</p>\n"
},
{
"type": "ManagedReference",
"source_relative_path": "_api_meta/client/EchoHub.Client.Services.UpdateChecker.yml",
@@ -850,6 +892,20 @@
"Title": "EchoHub.Core.Contracts.IMessageEncryptionService",
"Summary": null
},
{
"type": "ManagedReference",
"source_relative_path": "_api_meta/core/EchoHub.Core.Contracts.IUserService.yml",
"output": {
".html": {
"relative_path": "api/core/EchoHub.Core.Contracts.IUserService.html"
}
},
"version": "",
"Uid": null,
"IsMRef": true,
"Title": "EchoHub.Core.Contracts.IUserService",
"Summary": null
},
{
"type": "ManagedReference",
"source_relative_path": "_api_meta/core/EchoHub.Core.Contracts.yml",
@@ -1032,6 +1088,20 @@
"Title": "EchoHub.Core.DTOs.ErrorResponse",
"Summary": null
},
{
"type": "ManagedReference",
"source_relative_path": "_api_meta/core/EchoHub.Core.DTOs.JoinChannelResult.yml",
"output": {
".html": {
"relative_path": "api/core/EchoHub.Core.DTOs.JoinChannelResult.html"
}
},
"version": "",
"Uid": null,
"IsMRef": true,
"Title": "EchoHub.Core.DTOs.JoinChannelResult",
"Summary": null
},
{
"type": "ManagedReference",
"source_relative_path": "_api_meta/core/EchoHub.Core.DTOs.KickRequest.yml",
@@ -1242,6 +1312,34 @@
"Title": "EchoHub.Core.DTOs.UserDto",
"Summary": null
},
{
"type": "ManagedReference",
"source_relative_path": "_api_meta/core/EchoHub.Core.DTOs.UserError.yml",
"output": {
".html": {
"relative_path": "api/core/EchoHub.Core.DTOs.UserError.html"
}
},
"version": "",
"Uid": null,
"IsMRef": true,
"Title": "EchoHub.Core.DTOs.UserError",
"Summary": null
},
{
"type": "ManagedReference",
"source_relative_path": "_api_meta/core/EchoHub.Core.DTOs.UserOperationResult.yml",
"output": {
".html": {
"relative_path": "api/core/EchoHub.Core.DTOs.UserOperationResult.html"
}
},
"version": "",
"Uid": null,
"IsMRef": true,
"Title": "EchoHub.Core.DTOs.UserOperationResult",
"Summary": null
},
{
"type": "ManagedReference",
"source_relative_path": "_api_meta/core/EchoHub.Core.DTOs.UserPresenceDto.yml",
@@ -1956,6 +2054,20 @@
"Title": "EchoHub.Server.Services.MessageEncryptionService",
"Summary": null
},
{
"type": "ManagedReference",
"source_relative_path": "_api_meta/server/EchoHub.Server.Services.MuteExpirationService.yml",
"output": {
".html": {
"relative_path": "api/server/EchoHub.Server.Services.MuteExpirationService.html"
}
},
"version": "",
"Uid": null,
"IsMRef": true,
"Title": "EchoHub.Server.Services.MuteExpirationService",
"Summary": "<p sourcefile=\"_api_meta/server/EchoHub.Server.Services.MuteExpirationService.yml\" sourcestartlinenumber=\"1\">Background service that periodically unmutes users whose timed mute has expired.</p>\n"
},
{
"type": "ManagedReference",
"source_relative_path": "_api_meta/server/EchoHub.Server.Services.PresenceTracker.yml",
@@ -1998,6 +2110,20 @@
"Title": "EchoHub.Server.Services.SignalRBroadcaster",
"Summary": null
},
{
"type": "ManagedReference",
"source_relative_path": "_api_meta/server/EchoHub.Server.Services.UserService.yml",
"output": {
".html": {
"relative_path": "api/server/EchoHub.Server.Services.UserService.html"
}
},
"version": "",
"Uid": null,
"IsMRef": true,
"Title": "EchoHub.Server.Services.UserService",
"Summary": null
},
{
"type": "ManagedReference",
"source_relative_path": "_api_meta/server/EchoHub.Server.Services.yml",
@@ -2170,6 +2296,16 @@
},
"version": ""
},
{
"type": "Conceptual",
"source_relative_path": "articles/docker.md",
"output": {
".html": {
"relative_path": "articles/docker.html"
}
},
"version": ""
},
{
"type": "Conceptual",
"source_relative_path": "articles/encryption.md",
@@ -2336,6 +2472,99 @@
},
"version": ""
},
{
"type": "Conceptual",
"source_relative_path": "changelog/v0.2.8.md",
"output": {
".html": {
"relative_path": "changelog/v0.2.8.html"
}
},
"version": ""
},
{
"type": "Conceptual",
"source_relative_path": "flows/authentication.md",
"output": {
".html": {
"relative_path": "flows/authentication.html"
}
},
"version": ""
},
{
"type": "Conceptual",
"source_relative_path": "flows/channels.md",
"output": {
".html": {
"relative_path": "flows/channels.html"
}
},
"version": ""
},
{
"type": "Conceptual",
"source_relative_path": "flows/connection.md",
"output": {
".html": {
"relative_path": "flows/connection.html"
}
},
"version": ""
},
{
"type": "Conceptual",
"source_relative_path": "flows/flows.md",
"output": {
".html": {
"relative_path": "flows/flows.html"
}
},
"version": ""
},
{
"type": "Conceptual",
"source_relative_path": "flows/media.md",
"output": {
".html": {
"relative_path": "flows/media.html"
}
},
"version": ""
},
{
"type": "Conceptual",
"source_relative_path": "flows/messaging.md",
"output": {
".html": {
"relative_path": "flows/messaging.html"
}
},
"version": ""
},
{
"type": "Conceptual",
"source_relative_path": "flows/moderation.md",
"output": {
".html": {
"relative_path": "flows/moderation.html"
}
},
"version": ""
},
{
"type": "Toc",
"source_relative_path": "flows/toc.yml",
"output": {
".html": {
"relative_path": "flows/toc.html"
},
".json": {
"relative_path": "flows/toc.json"
}
},
"version": ""
},
{
"type": "Resource",
"source_relative_path": "images/hue_icon.svg",
@@ -2368,6 +2597,16 @@
}
},
"version": ""
},
{
"type": "Conceptual",
"source_relative_path": "todo.md",
"output": {
".html": {
"relative_path": "todo.html"
}
},
"version": ""
}
],
"groups": [
+3
View File
@@ -15,6 +15,9 @@
<li>
<a href="articles/getting-started.html" name="articles/toc.html" title="Articles">Articles</a>
</li>
<li>
<a href="flows/flows.html" name="flows/toc.html" title="Flows">Flows</a>
</li>
<li>
<a href="changelog/index.html" name="changelog/toc.html" title="Changelog">Changelog</a>
</li>
+1 -1
View File
@@ -1,2 +1,2 @@
{"items":[{"name":"Articles","href":"articles/getting-started.html","tocHref":"articles/toc.html","topicHref":"articles/getting-started.html","homepage":"articles/getting-started.html"},{"name":"Changelog","href":"changelog/index.html","tocHref":"changelog/toc.html","topicHref":"changelog/index.html","homepage":"changelog/index.html"},{"name":"API","href":"api/index.html","tocHref":"api/toc.html","topicHref":"api/index.html","homepage":"api/index.html"}]}
{"items":[{"name":"Articles","href":"articles/getting-started.html","tocHref":"articles/toc.html","topicHref":"articles/getting-started.html","homepage":"articles/getting-started.html"},{"name":"Flows","href":"flows/flows.html","tocHref":"flows/toc.html","topicHref":"flows/flows.html","homepage":"flows/flows.html"},{"name":"Changelog","href":"changelog/index.html","tocHref":"changelog/toc.html","topicHref":"changelog/index.html","homepage":"changelog/index.html"},{"name":"API","href":"api/index.html","tocHref":"api/toc.html","topicHref":"api/index.html","homepage":"api/index.html"}]}
+132
View File
@@ -0,0 +1,132 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>TODO | EchoHub Documentation </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="TODO | EchoHub Documentation ">
<link rel="icon" href="images/hue_icon.svg">
<link rel="stylesheet" href="public/docfx.min.css">
<link rel="stylesheet" href="public/main.css">
<meta name="docfx:navrel" content="toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:rel" content="">
<meta name="docfx:docurl" content="https://github.com/HueByte/EchoHub/blob/master/docs/#L1">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="index.html">
<img id="logo" class="svg" src="images/hue_icon.svg" alt="EchoHub">
EchoHub
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="content">
<div class="actionbar">
<nav id="breadcrumb"></nav>
</div>
<article data-uid="">
<h1 id="todo">TODO</h1>
<ul>
<li>[ ] fix the chat trailing; when user scrolls up, and somebody sends a message the chat instantly &quot;teleports&quot; to the very bottom</li>
<li>[x] disable the autorun of files (maybe keep for mp4? gotta do some sec research on it)</li>
<li>[x] when user creates a new channel, he gets moved to that channel; but the userlist does not refresh the state on that it refreshes when user re-enters the channel again</li>
<li>[ ] password protected rooms</li>
<li>[ ] better audio lib, current one (NetCoreAudio) does not support seek or other audio actions</li>
<li>[ ] Use options pattern for both client &amp; server
<ul>
<li>ref: <a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-10.0">https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-10.0</a></li>
</ul>
</li>
<li>[x] The vertical line of embeds should be the same colour as theme-color meta tag of the source</li>
<li>[x] change text wrapping to honor the offset of the user. (Preferably wrap whole words if they fit in on line. Basically how the CSS &quot;text-wrap-mode: wrap;&quot; works)</li>
<li>[x] make usernames in messages, mentions and in the user list clickable to open the user profile</li>
<li>[ ] Add tags support for public servers &amp; add filters on echohubspace for those tags in the server &quot;browser&quot;</li>
<li>[ ] when trying to /join a channel that doesn't exist a client side-ghost channel gets created that does not work</li>
<li>[x] unmute timer does not seem to work</li>
<li>[ ] add IRC network like support
<ul>
<li>that means basically multiple servers linked, so users can chat cross-server in this network</li>
</ul>
</li>
<li>[ ] when users clicks public -&gt; private -&gt; public checkbox in the channel creation, it ends up creating the channel on 3rd check switch</li>
<li>[ ] add keyboard only controls | at least for most important parts and the rest might be accessible with: (down)</li>
<li>[ ] add search bar / search modal that will allow users to instantly navigate to room / focus on app element &amp; etc</li>
<li>[ ] Actually smart data management cache messages, lazy load messages on scroll (currently hardcoded 100msgs fetched + new ones)</li>
<li>[x] Another thing would be stateful userlist basically fetch once and listen for userlist updates</li>
<li>[x] Send to EchohubSpace only state changes, currently we send user count periodically, instead of updating it on update</li>
<li>[x] space between mod|admin &quot;icon&quot; and username</li>
</ul>
</article>
<div class="contribution d-print-none">
<a href="https://github.com/HueByte/EchoHub/blob/master/docs/#L1" class="edit-link">Edit this page</a>
</div>
<div class="next-article d-print-none border-top" id="nextArticle"></div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<div class='footer-custom'><div class='footer-inner'><span class='footer-brand'>EchoHub</span><span class='footer-sep'>&middot;</span><a href='https://github.com/HueByte/EchoHub'>GitHub</a><span class='footer-sep'>&middot;</span><a href='https://echohub.voidcube.cloud'>Website</a><span class='footer-sep'>&middot;</span><span class='footer-credit'>Built with <a href='https://dotnet.github.io/docfx'>DocFX</a></span></div></div>
</div>
</div>
</footer>
</body>
</html>
+1176 -150
View File
File diff suppressed because it is too large Load Diff