diff --git a/api/core/EchoHub.Core.Models.ServerStatsReport.html b/api/core/EchoHub.Core.Models.ServerStatsReport.html new file mode 100644 index 0000000..133dee2 --- /dev/null +++ b/api/core/EchoHub.Core.Models.ServerStatsReport.html @@ -0,0 +1,757 @@ + + + + + Class ServerStatsReport | EchoHub Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
Table of Contents
+ +
+
+ +
+
+
+ +
+
+ + + +
+ +
+ + + +

+Class ServerStatsReport +

+ +
+
Namespace
EchoHub.Core.Models
+
Assembly
EchoHub.Core.dll
+
+ +

A snapshot of server activity over one reporting window, produced periodically by the +stats-report background job. Each report is logged as pretty-printed JSON and persisted +for historical trend analysis. The window is "since the previous report" (or since startup +for the first report of a run).

+
+
+ +
+
public class ServerStatsReport
+
+ + + + +
+
Inheritance
+
+ +
ServerStatsReport
+
+
+ + + +
+
Inherited Members
+
+ + + + + + + +
+ + + + + + +

Constructors +

+ + + + +

+ ServerStatsReport() + +

+ +
+
+ +
+
public ServerStatsReport()
+
+ + + + + + + + + + + + + +

Properties +

+ + + + +

+ ActiveMembers + +

+ +

Distinct users who sent at least one message during the window.

+
+
+ +
+
public int ActiveMembers { get; set; }
+
+ + + + + +

Property Value

+
+
int
+
+
+ + + + + + + + + + +

+ Bans + +

+ +

Users banned during the window.

+
+
+ +
+
public int Bans { get; set; }
+
+ + + + + +

Property Value

+
+
int
+
+
+ + + + + + + + + + +

+ BytesUploaded + +

+ +

Total bytes across all attachments uploaded during the window.

+
+
+ +
+
public long BytesUploaded { get; set; }
+
+ + + + + +

Property Value

+
+
long
+
+
+ + + + + + + + + + +

+ Connections + +

+ +

Session connects during the window (per-connection, across SignalR + IRC).

+
+
+ +
+
public int Connections { get; set; }
+
+ + + + + +

Property Value

+
+
int
+
+
+ + + + + + + + + + +

+ Disconnections + +

+ +

Session disconnects during the window ("members left" sessions).

+
+
+ +
+
public int Disconnections { get; set; }
+
+ + + + + +

Property Value

+
+
int
+
+
+ + + + + + + + + + +

+ FilesUploaded + +

+ +

Attachments (files/images/audio) uploaded during the window.

+
+
+ +
+
public int FilesUploaded { get; set; }
+
+ + + + + +

Property Value

+
+
int
+
+
+ + + + + + + + + + +

+ GeneratedAt + +

+ +

When this report was generated (equals PeriodEnd).

+
+
+ +
+
public DateTimeOffset GeneratedAt { get; set; }
+
+ + + + + +

Property Value

+
+
DateTimeOffset
+
+
+ + + + + + + + + + +

+ Id + +

+ +
+
+ +
+
public Guid Id { get; set; }
+
+ + + + + +

Property Value

+
+
Guid
+
+
+ + + + + + + + + + +

+ Kicks + +

+ +

Users kicked during the window.

+
+
+ +
+
public int Kicks { get; set; }
+
+ + + + + +

Property Value

+
+
int
+
+
+ + + + + + + + + + +

+ MessagesSent + +

+ +

Messages sent during the window.

+
+
+ +
+
public int MessagesSent { get; set; }
+
+ + + + + +

Property Value

+
+
int
+
+
+ + + + + + + + + + +

+ NewMembers + +

+ +

Accounts registered during the window ("new members joined").

+
+
+ +
+
public int NewMembers { get; set; }
+
+ + + + + +

Property Value

+
+
int
+
+
+ + + + + + + + + + +

+ OnlineNow + +

+ +

Distinct users online at window end.

+
+
+ +
+
public int OnlineNow { get; set; }
+
+ + + + + +

Property Value

+
+
int
+
+
+ + + + + + + + + + +

+ PeakOnline + +

+ +

Peak distinct users online observed during the window.

+
+
+ +
+
public int PeakOnline { get; set; }
+
+ + + + + +

Property Value

+
+
int
+
+
+ + + + + + + + + + +

+ PeriodEnd + +

+ +

End of the reporting window.

+
+
+ +
+
public DateTimeOffset PeriodEnd { get; set; }
+
+ + + + + +

Property Value

+
+
DateTimeOffset
+
+
+ + + + + + + + + + +

+ PeriodStart + +

+ +

Start of the reporting window.

+
+
+ +
+
public DateTimeOffset PeriodStart { get; set; }
+
+ + + + + +

Property Value

+
+
DateTimeOffset
+
+
+ + + + + + + + + + +

+ TotalMembers + +

+ +

Total registered (unique) members at window end.

+
+
+ +
+
public int TotalMembers { get; set; }
+
+ + + + + +

Property Value

+
+
int
+
+
+ + + + + + + + + + +

+ WindowHours + +

+ +

Length of the reporting window in hours.

+
+
+ +
+
public double WindowHours { get; set; }
+
+ + + + + +

Property Value

+
+
double
+
+
+ + + + + + + + + +
+ + + + +
+ +
+ +
+
+ +
+ + + + diff --git a/api/core/EchoHub.Core.Models.html b/api/core/EchoHub.Core.Models.html index ff32b58..e2677d0 100644 --- a/api/core/EchoHub.Core.Models.html +++ b/api/core/EchoHub.Core.Models.html @@ -122,6 +122,14 @@ new accounts (REST and IRC alike) require a valid, unexpired, not-fully-used cod
RefreshToken
+
+
ServerStatsReport
+

A snapshot of server activity over one reporting window, produced periodically by the +stats-report background job. Each report is logged as pretty-printed JSON and persisted +for historical trend analysis. The window is "since the previous report" (or since startup +for the first report of a run).

+
+
User
diff --git a/api/server/EchoHub.Server.Config.StatsOptions.html b/api/server/EchoHub.Server.Config.StatsOptions.html new file mode 100644 index 0000000..d338aeb --- /dev/null +++ b/api/server/EchoHub.Server.Config.StatsOptions.html @@ -0,0 +1,307 @@ + + + + + Class StatsOptions | EchoHub Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
Table of Contents
+ +
+
+ +
+
+
+ +
+
+ + + +
+ +
+ + + +

+Class StatsOptions +

+ +
+
Namespace
EchoHub.Server.Config
+
Assembly
EchoHub.Server.dll
+
+ +

Periodic server-stats report settings, bound from the "Stats" config section (env override: +Stats__Enabled etc.). When enabled, a background job periodically snapshots server +activity, logs it as pretty-printed JSON, and persists it to the database.

+
+
+ +
+
public sealed class StatsOptions
+
+ + + + +
+
Inheritance
+
+ +
StatsOptions
+
+
+ + + +
+
Inherited Members
+
+ + + + + + +
+ + + + + + +

Constructors +

+ + + + +

+ StatsOptions() + +

+ +
+
+ +
+
public StatsOptions()
+
+ + + + + + + + + + + + + +

Properties +

+ + + + +

+ Enabled + +

+ +

Master switch for the periodic stats report job.

+
+
+ +
+
public bool Enabled { get; set; }
+
+ + + + + +

Property Value

+
+
bool
+
+
+ + + + + + + + + + +

+ IntervalHours + +

+ +

How often a report is generated, in hours. Default: every 6 hours.

+
+
+ +
+
public double IntervalHours { get; set; }
+
+ + + + + +

Property Value

+
+
double
+
+
+ + + + + + + + + + +

+ RetentionDays + +

+ +

How long persisted reports are kept before being pruned, in days. Set to 0 to keep +reports indefinitely. Default: 90 days.

+
+
+ +
+
public int RetentionDays { get; set; }
+
+ + + + + +

Property Value

+
+
int
+
+
+ + + + + + + + + +
+ + + + +
+ +
+ +
+
+ +
+ + + + diff --git a/api/server/EchoHub.Server.Config.html b/api/server/EchoHub.Server.Config.html index 43a58c7..e3e232d 100644 --- a/api/server/EchoHub.Server.Config.html +++ b/api/server/EchoHub.Server.Config.html @@ -106,6 +106,13 @@ database; the rolling Serilog log files remain the only persistence.

SpamOptions

Anti-spam thresholds, bound from the "Spam" config section. Defaults are lenient enough that a fast typist never trips them; Mods and above are always exempt.

+
+
+
+
StatsOptions
+

Periodic server-stats report settings, bound from the "Stats" config section (env override: +Stats__Enabled etc.). When enabled, a background job periodically snapshots server +activity, logs it as pretty-printed JSON, and persists it to the database.

diff --git a/api/server/EchoHub.Server.Controllers.ChannelsController.html b/api/server/EchoHub.Server.Controllers.ChannelsController.html index 4212b3c..7ce1398 100644 --- a/api/server/EchoHub.Server.Controllers.ChannelsController.html +++ b/api/server/EchoHub.Server.Controllers.ChannelsController.html @@ -159,8 +159,8 @@ public class ChannelsController : ControllerBase -

- ChannelsController(IChannelService, EchoHubDbContext, FileStorageService, ImageToAsciiService, IHttpClientFactory, IChatService, IMessageEncryptionService, UploadLimits) +

+ ChannelsController(IChannelService, EchoHubDbContext, FileStorageService, ImageToAsciiService, IHttpClientFactory, IChatService, IMessageEncryptionService, UploadLimits, ILogger<ChannelsController>)

@@ -168,7 +168,7 @@ public class ChannelsController : ControllerBase
-
public ChannelsController(IChannelService channelService, EchoHubDbContext db, FileStorageService fileStorage, ImageToAsciiService asciiService, IHttpClientFactory httpClientFactory, IChatService chatService, IMessageEncryptionService encryption, UploadLimits uploadLimits)
+
public ChannelsController(IChannelService channelService, EchoHubDbContext db, FileStorageService fileStorage, ImageToAsciiService asciiService, IHttpClientFactory httpClientFactory, IChatService chatService, IMessageEncryptionService encryption, UploadLimits uploadLimits, ILogger<ChannelsController> logger)

Parameters

@@ -189,6 +189,8 @@ public class ChannelsController : ControllerBase
uploadLimits UploadLimits
+
logger ILogger<ChannelsController>
+
diff --git a/api/server/EchoHub.Server.Controllers.ModerationController.html b/api/server/EchoHub.Server.Controllers.ModerationController.html index 6477493..639196a 100644 --- a/api/server/EchoHub.Server.Controllers.ModerationController.html +++ b/api/server/EchoHub.Server.Controllers.ModerationController.html @@ -159,8 +159,8 @@ public class ModerationController : ControllerBase -

- ModerationController(EchoHubDbContext, IChatService, PresenceTracker, FileStorageService, IEnumerable<IChatBroadcaster>) +

+ ModerationController(EchoHubDbContext, IChatService, PresenceTracker, FileStorageService, IEnumerable<IChatBroadcaster>, ServerStatsCollector, ILogger<ModerationController>)

@@ -168,7 +168,7 @@ public class ModerationController : ControllerBase
-
public ModerationController(EchoHubDbContext db, IChatService chatService, PresenceTracker presenceTracker, FileStorageService fileStorage, IEnumerable<IChatBroadcaster> broadcasters)
+
public ModerationController(EchoHubDbContext db, IChatService chatService, PresenceTracker presenceTracker, FileStorageService fileStorage, IEnumerable<IChatBroadcaster> broadcasters, ServerStatsCollector statsCollector, ILogger<ModerationController> logger)

Parameters

@@ -183,6 +183,10 @@ public class ModerationController : ControllerBase
broadcasters IEnumerable<IChatBroadcaster>
+
statsCollector ServerStatsCollector
+
+
logger ILogger<ModerationController>
+
diff --git a/api/server/EchoHub.Server.Data.EchoHubDbContext.html b/api/server/EchoHub.Server.Data.EchoHubDbContext.html index 76af44e..033165b 100644 --- a/api/server/EchoHub.Server.Data.EchoHubDbContext.html +++ b/api/server/EchoHub.Server.Data.EchoHubDbContext.html @@ -381,6 +381,37 @@ Class EchoHubDbContext + +

+ ServerStatsReports + +

+ +
+
+ +
+
public DbSet<ServerStatsReport> ServerStatsReports { get; }
+
+ + + + + +

Property Value

+
+
DbSet<ServerStatsReport>
+
+
+ + + + + + + +

diff --git a/api/server/EchoHub.Server.Data.Migrations.AddServerStatsReports.html b/api/server/EchoHub.Server.Data.Migrations.AddServerStatsReports.html new file mode 100644 index 0000000..0aa43e4 --- /dev/null +++ b/api/server/EchoHub.Server.Data.Migrations.AddServerStatsReports.html @@ -0,0 +1,306 @@ + + + + + Class AddServerStatsReports | EchoHub Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
Table of Contents
+ +
+
+ +
+
+
+ +
+
+ + + +
+ +
+ + + +

+Class AddServerStatsReports +

+ +
+
Namespace
EchoHub.Server.Data.Migrations
+
Assembly
EchoHub.Server.dll
+
+ +
+
+ +
+
[DbContext(typeof(EchoHubDbContext))]
+[Migration("20260717200332_AddServerStatsReports")]
+public class AddServerStatsReports : Migration
+
+ + + + +
+
Inheritance
+
+ +
Migration
+
AddServerStatsReports
+
+
+ + + +
+
Inherited Members
+
+ + + + + + + +
+ + + + + + +

Constructors +

+ + + + +

+ AddServerStatsReports() + +

+ +
+
+ +
+
public AddServerStatsReports()
+
+ + + + + + + + + + + + + +

Methods +

+ + + + +

+ BuildTargetModel(ModelBuilder) + +

+ +
+
+ +
+
protected override void BuildTargetModel(ModelBuilder modelBuilder)
+
+ +

Parameters

+
+
modelBuilder ModelBuilder
+
+
+ + + + + + + + + + + + + + +

+ Down(MigrationBuilder) + +

+ +
+
+ +
+
protected override void Down(MigrationBuilder migrationBuilder)
+
+ +

Parameters

+
+
migrationBuilder MigrationBuilder
+
+
+ + + + + + + + + + + + + + +

+ Up(MigrationBuilder) + +

+ +
+
+ +
+
protected override void Up(MigrationBuilder migrationBuilder)
+
+ +

Parameters

+
+
migrationBuilder MigrationBuilder
+
+
+ + + + + + + + + + + + + +
+ + + + +
+ +
+ +
+
+ +
+ + + + diff --git a/api/server/EchoHub.Server.Data.Migrations.html b/api/server/EchoHub.Server.Data.Migrations.html index 2abd41b..eeef3a2 100644 --- a/api/server/EchoHub.Server.Data.Migrations.html +++ b/api/server/EchoHub.Server.Data.Migrations.html @@ -138,6 +138,10 @@ Classes
AddModerationRoles
+
+
AddServerStatsReports
+
+
InitialCreate
diff --git a/api/server/EchoHub.Server.Services.ChatService.html b/api/server/EchoHub.Server.Services.ChatService.html index 9683e87..71c8682 100644 --- a/api/server/EchoHub.Server.Services.ChatService.html +++ b/api/server/EchoHub.Server.Services.ChatService.html @@ -160,8 +160,8 @@ Class ChatService -

- ChatService(IServiceScopeFactory, PresenceTracker, IEnumerable<IChatBroadcaster>, LinkEmbedService, IMessageEncryptionService, IChannelService, FileStorageService, SpamGuard, ServerLogsService, ILogger<ChatService>) +

+ ChatService(IServiceScopeFactory, PresenceTracker, IEnumerable<IChatBroadcaster>, LinkEmbedService, IMessageEncryptionService, IChannelService, FileStorageService, SpamGuard, ServerLogsService, ServerStatsCollector, ILogger<ChatService>)

@@ -169,7 +169,7 @@ Class ChatService
-
public ChatService(IServiceScopeFactory scopeFactory, PresenceTracker presenceTracker, IEnumerable<IChatBroadcaster> broadcasters, LinkEmbedService embedService, IMessageEncryptionService encryption, IChannelService channelService, FileStorageService fileStorage, SpamGuard spamGuard, ServerLogsService serverLogs, ILogger<ChatService> logger)
+
public ChatService(IServiceScopeFactory scopeFactory, PresenceTracker presenceTracker, IEnumerable<IChatBroadcaster> broadcasters, LinkEmbedService embedService, IMessageEncryptionService encryption, IChannelService channelService, FileStorageService fileStorage, SpamGuard spamGuard, ServerLogsService serverLogs, ServerStatsCollector statsCollector, ILogger<ChatService> logger)

Parameters

@@ -192,6 +192,8 @@ Class ChatService
serverLogs ServerLogsService
+
statsCollector ServerStatsCollector
+
logger ILogger<ChatService>
diff --git a/api/server/EchoHub.Server.Services.Stats.ServerStatsCollector.html b/api/server/EchoHub.Server.Services.Stats.ServerStatsCollector.html new file mode 100644 index 0000000..505a7bd --- /dev/null +++ b/api/server/EchoHub.Server.Services.Stats.ServerStatsCollector.html @@ -0,0 +1,401 @@ + + + + + Class ServerStatsCollector | EchoHub Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
Table of Contents
+ +
+
+ +
+
+
+ +
+
+ + + +
+ +
+ + + +

+Class ServerStatsCollector +

+ +
+
Namespace
EchoHub.Server.Services.Stats
+
Assembly
EchoHub.Server.dll
+
+ +

Thread-safe, in-memory accumulator for server-activity counters that have no natural +database timestamp to query after the fact — session connects/disconnects, moderation +actions, and peak concurrency. The periodic stats-report job snapshots and resets these +once per reporting window. Registered as a singleton; every increment is lock-free so it +is safe to call from hot paths (connect/disconnect).

+
+
+ +
+
public sealed class ServerStatsCollector
+
+ + + + +
+
Inheritance
+
+ +
ServerStatsCollector
+
+
+ + + +
+
Inherited Members
+
+ + + + + + +
+ + + + + + +

Constructors +

+ + + + +

+ ServerStatsCollector() + +

+ +
+
+ +
+
public ServerStatsCollector()
+
+ + + + + + + + + + + + + +

Methods +

+ + + + +

+ RecordBan() + +

+ +

Record a ban action.

+
+
+ +
+
public void RecordBan()
+
+ + + + + + + + + + + + + + + +

+ RecordConnection(int) + +

+ +

Record a session coming online, updating the running peak.

+
+
+ +
+
public void RecordConnection(int onlineNow)
+
+ +

Parameters

+
+
onlineNow int
+
+
+ + + + + + + + + + + + + + +

+ RecordDisconnection(int) + +

+ +

Record a session going offline, updating the running peak.

+
+
+ +
+
public void RecordDisconnection(int onlineNow)
+
+ +

Parameters

+
+
onlineNow int
+
+
+ + + + + + + + + + + + + + +

+ RecordKick() + +

+ +

Record a kick action.

+
+
+ +
+
public void RecordKick()
+
+ + + + + + + + + + + + + + + +

+ RecordOnline(int) + +

+ +

Update the running maximum of concurrent online users (lock-free).

+
+
+ +
+
public void RecordOnline(int onlineNow)
+
+ +

Parameters

+
+
onlineNow int
+
+
+ + + + + + + + + + + + + + +

+ SnapshotAndReset(int) + +

+ +

Atomically read all counters and reset them for the next reporting window. The peak is +reset to onlineNow so the next window's peak starts from the current +concurrency rather than zero.

+
+
+ +
+
public StatsCounters SnapshotAndReset(int onlineNow)
+
+ +

Parameters

+
+
onlineNow int
+
+
+ +

Returns

+
+
StatsCounters
+
+
+ + + + + + + + + + + + +
+ + + + +
+ +
+ +
+
+ +
+ + + + diff --git a/api/server/EchoHub.Server.Services.Stats.ServerStatsReportService.html b/api/server/EchoHub.Server.Services.Stats.ServerStatsReportService.html new file mode 100644 index 0000000..e2ba561 --- /dev/null +++ b/api/server/EchoHub.Server.Services.Stats.ServerStatsReportService.html @@ -0,0 +1,267 @@ + + + + + Class ServerStatsReportService | EchoHub Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
Table of Contents
+ +
+
+ +
+
+
+ +
+
+ + + +
+ +
+ + + +

+Class ServerStatsReportService +

+ +
+
Namespace
EchoHub.Server.Services.Stats
+
Assembly
EchoHub.Server.dll
+
+ +

Background job that periodically snapshots server activity over a window, logs it as +pretty-printed JSON (which also surfaces in the live server-logs room), and persists it to +the database for historical trends. Interval and retention are configurable via the "Stats" +section; the default cadence is every 6 hours.

+
+
+ +
+
public sealed class ServerStatsReportService : BackgroundService, IDisposable
+
+ + + + +
+
Inheritance
+
+ +
BackgroundService
+
ServerStatsReportService
+
+
+ +
+
Implements
+
+ +
+
+ + +
+
Inherited Members
+
+ + + + + + +
+ + + + + + +

Constructors +

+ + + + +

+ ServerStatsReportService(IServiceScopeFactory, PresenceTracker, ServerStatsCollector, StatsOptions, ILogger<ServerStatsReportService>) + +

+ +
+
+ +
+
public ServerStatsReportService(IServiceScopeFactory scopeFactory, PresenceTracker presence, ServerStatsCollector collector, StatsOptions options, ILogger<ServerStatsReportService> logger)
+
+ +

Parameters

+
+
scopeFactory IServiceScopeFactory
+
+
presence PresenceTracker
+
+
collector ServerStatsCollector
+
+
options StatsOptions
+
+
logger ILogger<ServerStatsReportService>
+
+
+ + + + + + + + + + + + +

Methods +

+ + + + +

+ ExecuteAsync(CancellationToken) + +

+ +
+
+ +
+
protected override Task ExecuteAsync(CancellationToken stoppingToken)
+
+ +

Parameters

+
+
stoppingToken CancellationToken
+
+
+ +

Returns

+
+
Task
+
+
+ + + + + + + + + + + + +
+ + + + +
+ +
+ +
+
+ +
+ + + + diff --git a/api/server/EchoHub.Server.Services.Stats.StatsCounters.html b/api/server/EchoHub.Server.Services.Stats.StatsCounters.html new file mode 100644 index 0000000..fa17d12 --- /dev/null +++ b/api/server/EchoHub.Server.Services.Stats.StatsCounters.html @@ -0,0 +1,624 @@ + + + + + Struct StatsCounters | EchoHub Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
Table of Contents
+ +
+
+ +
+
+
+ +
+
+ + + +
+ +
+ + + +

+Struct StatsCounters +

+ +
+
Namespace
EchoHub.Server.Services.Stats
+
Assembly
EchoHub.Server.dll
+
+ +

Immutable snapshot of the counters held by ServerStatsCollector.

+
+
+ +
+
public readonly struct StatsCounters : IEquatable<StatsCounters>
+
+ + + + + +
+
Implements
+
+ +
+
+ + +
+
Inherited Members
+
+ + + +
+ + + + + + +

Constructors +

+ + + + +

+ StatsCounters(long, long, long, long, int) + +

+ +

Immutable snapshot of the counters held by ServerStatsCollector.

+
+
+ +
+
public StatsCounters(long Connections, long Disconnections, long Kicks, long Bans, int PeakOnline)
+
+ +

Parameters

+
+
Connections long
+
+
Disconnections long
+
+
Kicks long
+
+
Bans long
+
+
PeakOnline int
+
+
+ + + + + + + + + + + + +

Properties +

+ + + + +

+ Bans + +

+ +
+
+ +
+
public long Bans { get; init; }
+
+ + + + + +

Property Value

+
+
long
+
+
+ + + + + + + + + + +

+ Connections + +

+ +
+
+ +
+
public long Connections { get; init; }
+
+ + + + + +

Property Value

+
+
long
+
+
+ + + + + + + + + + +

+ Disconnections + +

+ +
+
+ +
+
public long Disconnections { get; init; }
+
+ + + + + +

Property Value

+
+
long
+
+
+ + + + + + + + + + +

+ Kicks + +

+ +
+
+ +
+
public long Kicks { get; init; }
+
+ + + + + +

Property Value

+
+
long
+
+
+ + + + + + + + + + +

+ PeakOnline + +

+ +
+
+ +
+
public int PeakOnline { get; init; }
+
+ + + + + +

Property Value

+
+
int
+
+
+ + + + + + + + +

Methods +

+ + + + +

+ Deconstruct(out long, out long, out long, out long, out int) + +

+ +
+
+ +
+
public void Deconstruct(out long Connections, out long Disconnections, out long Kicks, out long Bans, out int PeakOnline)
+
+ +

Parameters

+
+
Connections long
+
+
Disconnections long
+
+
Kicks long
+
+
Bans long
+
+
PeakOnline int
+
+
+ + + + + + + + + + + + + + +

+ Equals(StatsCounters) + +

+ +
+
+ +
+
public bool Equals(StatsCounters other)
+
+ +

Parameters

+
+
other StatsCounters
+
+
+ +

Returns

+
+
bool
+
+
+ + + + + + + + + + + + + +

+ Equals(object) + +

+ +
+
+ +
+
public override bool Equals(object obj)
+
+ +

Parameters

+
+
obj object
+
+
+ +

Returns

+
+
bool
+
+
+ + + + + + + + + + + + + +

+ GetHashCode() + +

+ +
+
+ +
+
public override int GetHashCode()
+
+ + +

Returns

+
+
int
+
+
+ + + + + + + + + + + + + +

+ ToString() + +

+ +
+
+ +
+
public override string ToString()
+
+ + +

Returns

+
+
string
+
+
+ + + + + + + + + + + +

Operators +

+ + + + +

+ operator ==(StatsCounters, StatsCounters) + +

+ +
+
+ +
+
public static bool operator ==(StatsCounters left, StatsCounters right)
+
+ +

Parameters

+
+
left StatsCounters
+
+
right StatsCounters
+
+
+ +

Returns

+
+
bool
+
+
+ + + + + + + + + + + + + +

+ operator !=(StatsCounters, StatsCounters) + +

+ +
+
+ +
+
public static bool operator !=(StatsCounters left, StatsCounters right)
+
+ +

Parameters

+
+
left StatsCounters
+
+
right StatsCounters
+
+
+ +

Returns

+
+
bool
+
+
+ + + + + + + + + + + + +
+ + + + +
+ +
+ +
+
+ +
+ + + + diff --git a/api/server/EchoHub.Server.Services.Stats.html b/api/server/EchoHub.Server.Services.Stats.html new file mode 100644 index 0000000..c7794f7 --- /dev/null +++ b/api/server/EchoHub.Server.Services.Stats.html @@ -0,0 +1,147 @@ + + + + + Namespace EchoHub.Server.Services.Stats | EchoHub Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
Table of Contents
+ +
+
+ +
+
+
+ +
+
+ + + +
+ +
+ +

Namespace EchoHub.Server.Services.Stats

+
+
+
+ +

+Classes +

+
+
ServerStatsCollector
+

Thread-safe, in-memory accumulator for server-activity counters that have no natural +database timestamp to query after the fact — session connects/disconnects, moderation +actions, and peak concurrency. The periodic stats-report job snapshots and resets these +once per reporting window. Registered as a singleton; every increment is lock-free so it +is safe to call from hot paths (connect/disconnect).

+
+
+
+
ServerStatsReportService
+

Background job that periodically snapshots server activity over a window, logs it as +pretty-printed JSON (which also surfaces in the live server-logs room), and persists it to +the database for historical trends. Interval and retention are configurable via the "Stats" +section; the default cadence is every 6 hours.

+
+
+

+Structs +

+
+
StatsCounters
+

Immutable snapshot of the counters held by ServerStatsCollector.

+
+
+ + +
+ +
+
+ + +
+ +
+ +
+
+ +
+ + + + diff --git a/api/toc.html b/api/toc.html index e12dd5f..7da75e1 100644 --- a/api/toc.html +++ b/api/toc.html @@ -517,6 +517,9 @@
  • ServerRole
  • +
  • + ServerStatsReport +
  • User
  • @@ -599,6 +602,9 @@
  • SpamOptions
  • +
  • + StatsOptions +
  • UploadLimits
  • @@ -680,6 +686,9 @@
  • AddModerationRoles
  • +
  • + AddServerStatsReports +
  • InitialCreate
  • @@ -769,6 +778,22 @@ +
  • + + EchoHub.Server.Services.Stats + + +
  • EchoHub.Server.Setup diff --git a/api/toc.json b/api/toc.json index cb37ac8..092cd3b 100644 --- a/api/toc.json +++ b/api/toc.json @@ -1,2 +1,2 @@ -{"items":[{"name":"Client","items":[{"name":"API Reference","includedFrom":"~/_api_meta/client/toc.yml","items":[{"name":"EchoHub.Client","href":"client/EchoHub.Client.html","topicHref":"client/EchoHub.Client.html","topicUid":"EchoHub.Client","type":"Namespace","items":[{"name":"AppOrchestrator","href":"client/EchoHub.Client.AppOrchestrator.html","topicHref":"client/EchoHub.Client.AppOrchestrator.html","topicUid":"EchoHub.Client.AppOrchestrator","type":"Class"}]},{"name":"EchoHub.Client.Commands","href":"client/EchoHub.Client.Commands.html","topicHref":"client/EchoHub.Client.Commands.html","topicUid":"EchoHub.Client.Commands","type":"Namespace","items":[{"name":"CommandHandler","href":"client/EchoHub.Client.Commands.CommandHandler.html","topicHref":"client/EchoHub.Client.Commands.CommandHandler.html","topicUid":"EchoHub.Client.Commands.CommandHandler","type":"Class"},{"name":"CommandResult","href":"client/EchoHub.Client.Commands.CommandResult.html","topicHref":"client/EchoHub.Client.Commands.CommandResult.html","topicUid":"EchoHub.Client.Commands.CommandResult","type":"Class"}]},{"name":"EchoHub.Client.Config","href":"client/EchoHub.Client.Config.html","topicHref":"client/EchoHub.Client.Config.html","topicUid":"EchoHub.Client.Config","type":"Namespace","items":[{"name":"AccountPreset","href":"client/EchoHub.Client.Config.AccountPreset.html","topicHref":"client/EchoHub.Client.Config.AccountPreset.html","topicUid":"EchoHub.Client.Config.AccountPreset","type":"Class"},{"name":"ClientConfig","href":"client/EchoHub.Client.Config.ClientConfig.html","topicHref":"client/EchoHub.Client.Config.ClientConfig.html","topicUid":"EchoHub.Client.Config.ClientConfig","type":"Class"},{"name":"ConfigManager","href":"client/EchoHub.Client.Config.ConfigManager.html","topicHref":"client/EchoHub.Client.Config.ConfigManager.html","topicUid":"EchoHub.Client.Config.ConfigManager","type":"Class"},{"name":"NotificationConfig","href":"client/EchoHub.Client.Config.NotificationConfig.html","topicHref":"client/EchoHub.Client.Config.NotificationConfig.html","topicUid":"EchoHub.Client.Config.NotificationConfig","type":"Class"},{"name":"SavedServer","href":"client/EchoHub.Client.Config.SavedServer.html","topicHref":"client/EchoHub.Client.Config.SavedServer.html","topicUid":"EchoHub.Client.Config.SavedServer","type":"Class"}]},{"name":"EchoHub.Client.Services","href":"client/EchoHub.Client.Services.html","topicHref":"client/EchoHub.Client.Services.html","topicUid":"EchoHub.Client.Services","type":"Namespace","items":[{"name":"ApiClient","href":"client/EchoHub.Client.Services.ApiClient.html","topicHref":"client/EchoHub.Client.Services.ApiClient.html","topicUid":"EchoHub.Client.Services.ApiClient","type":"Class"},{"name":"AsyncRunner","href":"client/EchoHub.Client.Services.AsyncRunner.html","topicHref":"client/EchoHub.Client.Services.AsyncRunner.html","topicUid":"EchoHub.Client.Services.AsyncRunner","type":"Class"},{"name":"AudioPlaybackService","href":"client/EchoHub.Client.Services.AudioPlaybackService.html","topicHref":"client/EchoHub.Client.Services.AudioPlaybackService.html","topicUid":"EchoHub.Client.Services.AudioPlaybackService","type":"Class"},{"name":"BackupInfo","href":"client/EchoHub.Client.Services.BackupInfo.html","topicHref":"client/EchoHub.Client.Services.BackupInfo.html","topicUid":"EchoHub.Client.Services.BackupInfo","type":"Class"},{"name":"ChannelPasswordRequiredException","href":"client/EchoHub.Client.Services.ChannelPasswordRequiredException.html","topicHref":"client/EchoHub.Client.Services.ChannelPasswordRequiredException.html","topicUid":"EchoHub.Client.Services.ChannelPasswordRequiredException","type":"Class"},{"name":"ClientEncryptionService","href":"client/EchoHub.Client.Services.ClientEncryptionService.html","topicHref":"client/EchoHub.Client.Services.ClientEncryptionService.html","topicUid":"EchoHub.Client.Services.ClientEncryptionService","type":"Class"},{"name":"ClipboardFiles","href":"client/EchoHub.Client.Services.ClipboardFiles.html","topicHref":"client/EchoHub.Client.Services.ClipboardFiles.html","topicUid":"EchoHub.Client.Services.ClipboardFiles","type":"Class"},{"name":"ClipboardImage","href":"client/EchoHub.Client.Services.ClipboardImage.html","topicHref":"client/EchoHub.Client.Services.ClipboardImage.html","topicUid":"EchoHub.Client.Services.ClipboardImage","type":"Class"},{"name":"EchoHubConnection","href":"client/EchoHub.Client.Services.EchoHubConnection.html","topicHref":"client/EchoHub.Client.Services.EchoHubConnection.html","topicUid":"EchoHub.Client.Services.EchoHubConnection","type":"Class"},{"name":"FolderPickResult","href":"client/EchoHub.Client.Services.FolderPickResult.html","topicHref":"client/EchoHub.Client.Services.FolderPickResult.html","topicUid":"EchoHub.Client.Services.FolderPickResult","type":"Class"},{"name":"JoinOutcome","href":"client/EchoHub.Client.Services.JoinOutcome.html","topicHref":"client/EchoHub.Client.Services.JoinOutcome.html","topicUid":"EchoHub.Client.Services.JoinOutcome","type":"Class"},{"name":"NativeFolderPicker","href":"client/EchoHub.Client.Services.NativeFolderPicker.html","topicHref":"client/EchoHub.Client.Services.NativeFolderPicker.html","topicUid":"EchoHub.Client.Services.NativeFolderPicker","type":"Class"},{"name":"NotificationSoundService","href":"client/EchoHub.Client.Services.NotificationSoundService.html","topicHref":"client/EchoHub.Client.Services.NotificationSoundService.html","topicUid":"EchoHub.Client.Services.NotificationSoundService","type":"Class"},{"name":"OutgoingAttachment","href":"client/EchoHub.Client.Services.OutgoingAttachment.html","topicHref":"client/EchoHub.Client.Services.OutgoingAttachment.html","topicUid":"EchoHub.Client.Services.OutgoingAttachment","type":"Class"},{"name":"PathSetup","href":"client/EchoHub.Client.Services.PathSetup.html","topicHref":"client/EchoHub.Client.Services.PathSetup.html","topicUid":"EchoHub.Client.Services.PathSetup","type":"Class"},{"name":"PickerOutcome","href":"client/EchoHub.Client.Services.PickerOutcome.html","topicHref":"client/EchoHub.Client.Services.PickerOutcome.html","topicUid":"EchoHub.Client.Services.PickerOutcome","type":"Enum"},{"name":"RoomKeyProtector","href":"client/EchoHub.Client.Services.RoomKeyProtector.html","topicHref":"client/EchoHub.Client.Services.RoomKeyProtector.html","topicUid":"EchoHub.Client.Services.RoomKeyProtector","type":"Class"},{"name":"RoomKeyStore","href":"client/EchoHub.Client.Services.RoomKeyStore.html","topicHref":"client/EchoHub.Client.Services.RoomKeyStore.html","topicUid":"EchoHub.Client.Services.RoomKeyStore","type":"Class"},{"name":"RoomLockedException","href":"client/EchoHub.Client.Services.RoomLockedException.html","topicHref":"client/EchoHub.Client.Services.RoomLockedException.html","topicUid":"EchoHub.Client.Services.RoomLockedException","type":"Class"},{"name":"UpdateBackupService","href":"client/EchoHub.Client.Services.UpdateBackupService.html","topicHref":"client/EchoHub.Client.Services.UpdateBackupService.html","topicUid":"EchoHub.Client.Services.UpdateBackupService","type":"Class"},{"name":"UpdateChecker","href":"client/EchoHub.Client.Services.UpdateChecker.html","topicHref":"client/EchoHub.Client.Services.UpdateChecker.html","topicUid":"EchoHub.Client.Services.UpdateChecker","type":"Class"}]},{"name":"EchoHub.Client.Themes","href":"client/EchoHub.Client.Themes.html","topicHref":"client/EchoHub.Client.Themes.html","topicUid":"EchoHub.Client.Themes","type":"Namespace","items":[{"name":"Theme","href":"client/EchoHub.Client.Themes.Theme.html","topicHref":"client/EchoHub.Client.Themes.Theme.html","topicUid":"EchoHub.Client.Themes.Theme","type":"Class"},{"name":"ThemeColors","href":"client/EchoHub.Client.Themes.ThemeColors.html","topicHref":"client/EchoHub.Client.Themes.ThemeColors.html","topicUid":"EchoHub.Client.Themes.ThemeColors","type":"Class"},{"name":"ThemeManager","href":"client/EchoHub.Client.Themes.ThemeManager.html","topicHref":"client/EchoHub.Client.Themes.ThemeManager.html","topicUid":"EchoHub.Client.Themes.ThemeManager","type":"Class"}]},{"name":"EchoHub.Client.UI","href":"client/EchoHub.Client.UI.html","topicHref":"client/EchoHub.Client.UI.html","topicUid":"EchoHub.Client.UI","type":"Namespace","items":[{"name":"MainWindow","href":"client/EchoHub.Client.UI.MainWindow.html","topicHref":"client/EchoHub.Client.UI.MainWindow.html","topicUid":"EchoHub.Client.UI.MainWindow","type":"Class"}]},{"name":"EchoHub.Client.UI.Chat","href":"client/EchoHub.Client.UI.Chat.html","topicHref":"client/EchoHub.Client.UI.Chat.html","topicUid":"EchoHub.Client.UI.Chat","type":"Namespace","items":[{"name":"AttachmentAction","href":"client/EchoHub.Client.UI.Chat.AttachmentAction.html","topicHref":"client/EchoHub.Client.UI.Chat.AttachmentAction.html","topicUid":"EchoHub.Client.UI.Chat.AttachmentAction","type":"Enum"},{"name":"AttachmentActionSpan","href":"client/EchoHub.Client.UI.Chat.AttachmentActionSpan.html","topicHref":"client/EchoHub.Client.UI.Chat.AttachmentActionSpan.html","topicUid":"EchoHub.Client.UI.Chat.AttachmentActionSpan","type":"Struct"},{"name":"ChatColors","href":"client/EchoHub.Client.UI.Chat.ChatColors.html","topicHref":"client/EchoHub.Client.UI.Chat.ChatColors.html","topicUid":"EchoHub.Client.UI.Chat.ChatColors","type":"Class"},{"name":"ChatLine","href":"client/EchoHub.Client.UI.Chat.ChatLine.html","topicHref":"client/EchoHub.Client.UI.Chat.ChatLine.html","topicUid":"EchoHub.Client.UI.Chat.ChatLine","type":"Class"},{"name":"ChatListSource","href":"client/EchoHub.Client.UI.Chat.ChatListSource.html","topicHref":"client/EchoHub.Client.UI.Chat.ChatListSource.html","topicUid":"EchoHub.Client.UI.Chat.ChatListSource","type":"Class"},{"name":"ChatMessageManager","href":"client/EchoHub.Client.UI.Chat.ChatMessageManager.html","topicHref":"client/EchoHub.Client.UI.Chat.ChatMessageManager.html","topicUid":"EchoHub.Client.UI.Chat.ChatMessageManager","type":"Class"},{"name":"ChatSegment","href":"client/EchoHub.Client.UI.Chat.ChatSegment.html","topicHref":"client/EchoHub.Client.UI.Chat.ChatSegment.html","topicUid":"EchoHub.Client.UI.Chat.ChatSegment","type":"Class"}]},{"name":"EchoHub.Client.UI.Dialogs","href":"client/EchoHub.Client.UI.Dialogs.html","topicHref":"client/EchoHub.Client.UI.Dialogs.html","topicUid":"EchoHub.Client.UI.Dialogs","type":"Namespace","items":[{"name":"AudioPlayerDialog","href":"client/EchoHub.Client.UI.Dialogs.AudioPlayerDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.AudioPlayerDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.AudioPlayerDialog","type":"Class"},{"name":"ChannelPasswordDialog","href":"client/EchoHub.Client.UI.Dialogs.ChannelPasswordDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ChannelPasswordDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.ChannelPasswordDialog","type":"Class"},{"name":"ConnectDialog","href":"client/EchoHub.Client.UI.Dialogs.ConnectDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ConnectDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.ConnectDialog","type":"Class"},{"name":"ConnectDialogResult","href":"client/EchoHub.Client.UI.Dialogs.ConnectDialogResult.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ConnectDialogResult.html","topicUid":"EchoHub.Client.UI.Dialogs.ConnectDialogResult","type":"Class"},{"name":"CreateChannelDialog","href":"client/EchoHub.Client.UI.Dialogs.CreateChannelDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.CreateChannelDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.CreateChannelDialog","type":"Class"},{"name":"CreateChannelResult","href":"client/EchoHub.Client.UI.Dialogs.CreateChannelResult.html","topicHref":"client/EchoHub.Client.UI.Dialogs.CreateChannelResult.html","topicUid":"EchoHub.Client.UI.Dialogs.CreateChannelResult","type":"Class"},{"name":"ProfileAction","href":"client/EchoHub.Client.UI.Dialogs.ProfileAction.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ProfileAction.html","topicUid":"EchoHub.Client.UI.Dialogs.ProfileAction","type":"Enum"},{"name":"ProfileEditDialog","href":"client/EchoHub.Client.UI.Dialogs.ProfileEditDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ProfileEditDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.ProfileEditDialog","type":"Class"},{"name":"ProfileEditResult","href":"client/EchoHub.Client.UI.Dialogs.ProfileEditResult.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ProfileEditResult.html","topicUid":"EchoHub.Client.UI.Dialogs.ProfileEditResult","type":"Class"},{"name":"ProfileViewDialog","href":"client/EchoHub.Client.UI.Dialogs.ProfileViewDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ProfileViewDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.ProfileViewDialog","type":"Class"},{"name":"SearchDialog","href":"client/EchoHub.Client.UI.Dialogs.SearchDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.SearchDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.SearchDialog","type":"Class"},{"name":"SearchResult","href":"client/EchoHub.Client.UI.Dialogs.SearchResult.html","topicHref":"client/EchoHub.Client.UI.Dialogs.SearchResult.html","topicUid":"EchoHub.Client.UI.Dialogs.SearchResult","type":"Class"},{"name":"SearchResultType","href":"client/EchoHub.Client.UI.Dialogs.SearchResultType.html","topicHref":"client/EchoHub.Client.UI.Dialogs.SearchResultType.html","topicUid":"EchoHub.Client.UI.Dialogs.SearchResultType","type":"Enum"},{"name":"StatusDialog","href":"client/EchoHub.Client.UI.Dialogs.StatusDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.StatusDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.StatusDialog","type":"Class"},{"name":"StatusDialogResult","href":"client/EchoHub.Client.UI.Dialogs.StatusDialogResult.html","topicHref":"client/EchoHub.Client.UI.Dialogs.StatusDialogResult.html","topicUid":"EchoHub.Client.UI.Dialogs.StatusDialogResult","type":"Class"},{"name":"UpdateConfirmDialog","href":"client/EchoHub.Client.UI.Dialogs.UpdateConfirmDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.UpdateConfirmDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.UpdateConfirmDialog","type":"Class"}]},{"name":"EchoHub.Client.UI.Helpers","href":"client/EchoHub.Client.UI.Helpers.html","topicHref":"client/EchoHub.Client.UI.Helpers.html","topicUid":"EchoHub.Client.UI.Helpers","type":"Namespace","items":[{"name":"DroppedFileParser","href":"client/EchoHub.Client.UI.Helpers.DroppedFileParser.html","topicHref":"client/EchoHub.Client.UI.Helpers.DroppedFileParser.html","topicUid":"EchoHub.Client.UI.Helpers.DroppedFileParser","type":"Class"},{"name":"EmojiHelper","href":"client/EchoHub.Client.UI.Helpers.EmojiHelper.html","topicHref":"client/EchoHub.Client.UI.Helpers.EmojiHelper.html","topicUid":"EchoHub.Client.UI.Helpers.EmojiHelper","type":"Class"},{"name":"HexColorHelper","href":"client/EchoHub.Client.UI.Helpers.HexColorHelper.html","topicHref":"client/EchoHub.Client.UI.Helpers.HexColorHelper.html","topicUid":"EchoHub.Client.UI.Helpers.HexColorHelper","type":"Class"},{"name":"NickColorHelper","href":"client/EchoHub.Client.UI.Helpers.NickColorHelper.html","topicHref":"client/EchoHub.Client.UI.Helpers.NickColorHelper.html","topicUid":"EchoHub.Client.UI.Helpers.NickColorHelper","type":"Class"}]},{"name":"EchoHub.Client.UI.ListSources","href":"client/EchoHub.Client.UI.ListSources.html","topicHref":"client/EchoHub.Client.UI.ListSources.html","topicUid":"EchoHub.Client.UI.ListSources","type":"Namespace","items":[{"name":"ChannelListSource","href":"client/EchoHub.Client.UI.ListSources.ChannelListSource.html","topicHref":"client/EchoHub.Client.UI.ListSources.ChannelListSource.html","topicUid":"EchoHub.Client.UI.ListSources.ChannelListSource","type":"Class"},{"name":"SearchListSource","href":"client/EchoHub.Client.UI.ListSources.SearchListSource.html","topicHref":"client/EchoHub.Client.UI.ListSources.SearchListSource.html","topicUid":"EchoHub.Client.UI.ListSources.SearchListSource","type":"Class"},{"name":"UserListSource","href":"client/EchoHub.Client.UI.ListSources.UserListSource.html","topicHref":"client/EchoHub.Client.UI.ListSources.UserListSource.html","topicUid":"EchoHub.Client.UI.ListSources.UserListSource","type":"Class"}]}]},{"name":"Articles","includedFrom":"~/api/client-articles/toc.yml","items":[{"name":"Overview","href":"client-articles/index.html","topicHref":"client-articles/index.html"}]}]},{"name":"Core","items":[{"name":"API Reference","includedFrom":"~/_api_meta/core/toc.yml","items":[{"name":"EchoHub.Core.Constants","href":"core/EchoHub.Core.Constants.html","topicHref":"core/EchoHub.Core.Constants.html","topicUid":"EchoHub.Core.Constants","type":"Namespace","items":[{"name":"HubConstants","href":"core/EchoHub.Core.Constants.HubConstants.html","topicHref":"core/EchoHub.Core.Constants.HubConstants.html","topicUid":"EchoHub.Core.Constants.HubConstants","type":"Class"},{"name":"MessageConventions","href":"core/EchoHub.Core.Constants.MessageConventions.html","topicHref":"core/EchoHub.Core.Constants.MessageConventions.html","topicUid":"EchoHub.Core.Constants.MessageConventions","type":"Class"},{"name":"ValidationConstants","href":"core/EchoHub.Core.Constants.ValidationConstants.html","topicHref":"core/EchoHub.Core.Constants.ValidationConstants.html","topicUid":"EchoHub.Core.Constants.ValidationConstants","type":"Class"}]},{"name":"EchoHub.Core.Contracts","href":"core/EchoHub.Core.Contracts.html","topicHref":"core/EchoHub.Core.Contracts.html","topicUid":"EchoHub.Core.Contracts","type":"Namespace","items":[{"name":"ChannelListItem","href":"core/EchoHub.Core.Contracts.ChannelListItem.html","topicHref":"core/EchoHub.Core.Contracts.ChannelListItem.html","topicUid":"EchoHub.Core.Contracts.ChannelListItem","type":"Class"},{"name":"IChannelService","href":"core/EchoHub.Core.Contracts.IChannelService.html","topicHref":"core/EchoHub.Core.Contracts.IChannelService.html","topicUid":"EchoHub.Core.Contracts.IChannelService","type":"Interface"},{"name":"IChatBroadcaster","href":"core/EchoHub.Core.Contracts.IChatBroadcaster.html","topicHref":"core/EchoHub.Core.Contracts.IChatBroadcaster.html","topicUid":"EchoHub.Core.Contracts.IChatBroadcaster","type":"Interface"},{"name":"IChatService","href":"core/EchoHub.Core.Contracts.IChatService.html","topicHref":"core/EchoHub.Core.Contracts.IChatService.html","topicUid":"EchoHub.Core.Contracts.IChatService","type":"Interface"},{"name":"IEchoHubClient","href":"core/EchoHub.Core.Contracts.IEchoHubClient.html","topicHref":"core/EchoHub.Core.Contracts.IEchoHubClient.html","topicUid":"EchoHub.Core.Contracts.IEchoHubClient","type":"Interface"},{"name":"IMessageEncryptionService","href":"core/EchoHub.Core.Contracts.IMessageEncryptionService.html","topicHref":"core/EchoHub.Core.Contracts.IMessageEncryptionService.html","topicUid":"EchoHub.Core.Contracts.IMessageEncryptionService","type":"Interface"},{"name":"IUserService","href":"core/EchoHub.Core.Contracts.IUserService.html","topicHref":"core/EchoHub.Core.Contracts.IUserService.html","topicUid":"EchoHub.Core.Contracts.IUserService","type":"Interface"}]},{"name":"EchoHub.Core.DTOs","href":"core/EchoHub.Core.DTOs.html","topicHref":"core/EchoHub.Core.DTOs.html","topicUid":"EchoHub.Core.DTOs","type":"Namespace","items":[{"name":"ApiResponse","href":"core/EchoHub.Core.DTOs.ApiResponse.html","topicHref":"core/EchoHub.Core.DTOs.ApiResponse.html","topicUid":"EchoHub.Core.DTOs.ApiResponse","type":"Class"},{"name":"ApiResponse","href":"core/EchoHub.Core.DTOs.ApiResponse-1.html","topicHref":"core/EchoHub.Core.DTOs.ApiResponse-1.html","topicUid":"EchoHub.Core.DTOs.ApiResponse`1","type":"Class"},{"name":"AssignRoleRequest","href":"core/EchoHub.Core.DTOs.AssignRoleRequest.html","topicHref":"core/EchoHub.Core.DTOs.AssignRoleRequest.html","topicUid":"EchoHub.Core.DTOs.AssignRoleRequest","type":"Class"},{"name":"AttachmentDto","href":"core/EchoHub.Core.DTOs.AttachmentDto.html","topicHref":"core/EchoHub.Core.DTOs.AttachmentDto.html","topicUid":"EchoHub.Core.DTOs.AttachmentDto","type":"Class"},{"name":"AvatarUploadResponse","href":"core/EchoHub.Core.DTOs.AvatarUploadResponse.html","topicHref":"core/EchoHub.Core.DTOs.AvatarUploadResponse.html","topicUid":"EchoHub.Core.DTOs.AvatarUploadResponse","type":"Class"},{"name":"BanRequest","href":"core/EchoHub.Core.DTOs.BanRequest.html","topicHref":"core/EchoHub.Core.DTOs.BanRequest.html","topicUid":"EchoHub.Core.DTOs.BanRequest","type":"Class"},{"name":"ChannelCryptoDto","href":"core/EchoHub.Core.DTOs.ChannelCryptoDto.html","topicHref":"core/EchoHub.Core.DTOs.ChannelCryptoDto.html","topicUid":"EchoHub.Core.DTOs.ChannelCryptoDto","type":"Class"},{"name":"ChannelDto","href":"core/EchoHub.Core.DTOs.ChannelDto.html","topicHref":"core/EchoHub.Core.DTOs.ChannelDto.html","topicUid":"EchoHub.Core.DTOs.ChannelDto","type":"Class"},{"name":"ChannelError","href":"core/EchoHub.Core.DTOs.ChannelError.html","topicHref":"core/EchoHub.Core.DTOs.ChannelError.html","topicUid":"EchoHub.Core.DTOs.ChannelError","type":"Enum"},{"name":"ChannelMetaDto","href":"core/EchoHub.Core.DTOs.ChannelMetaDto.html","topicHref":"core/EchoHub.Core.DTOs.ChannelMetaDto.html","topicUid":"EchoHub.Core.DTOs.ChannelMetaDto","type":"Class"},{"name":"ChannelOperationResult","href":"core/EchoHub.Core.DTOs.ChannelOperationResult.html","topicHref":"core/EchoHub.Core.DTOs.ChannelOperationResult.html","topicUid":"EchoHub.Core.DTOs.ChannelOperationResult","type":"Class"},{"name":"CreateChannelRequest","href":"core/EchoHub.Core.DTOs.CreateChannelRequest.html","topicHref":"core/EchoHub.Core.DTOs.CreateChannelRequest.html","topicUid":"EchoHub.Core.DTOs.CreateChannelRequest","type":"Class"},{"name":"CreateInviteRequest","href":"core/EchoHub.Core.DTOs.CreateInviteRequest.html","topicHref":"core/EchoHub.Core.DTOs.CreateInviteRequest.html","topicUid":"EchoHub.Core.DTOs.CreateInviteRequest","type":"Class"},{"name":"DeleteAccountRequest","href":"core/EchoHub.Core.DTOs.DeleteAccountRequest.html","topicHref":"core/EchoHub.Core.DTOs.DeleteAccountRequest.html","topicUid":"EchoHub.Core.DTOs.DeleteAccountRequest","type":"Class"},{"name":"EmbedDto","href":"core/EchoHub.Core.DTOs.EmbedDto.html","topicHref":"core/EchoHub.Core.DTOs.EmbedDto.html","topicUid":"EchoHub.Core.DTOs.EmbedDto","type":"Class"},{"name":"EncryptionKeyResponse","href":"core/EchoHub.Core.DTOs.EncryptionKeyResponse.html","topicHref":"core/EchoHub.Core.DTOs.EncryptionKeyResponse.html","topicUid":"EchoHub.Core.DTOs.EncryptionKeyResponse","type":"Class"},{"name":"ErrorResponse","href":"core/EchoHub.Core.DTOs.ErrorResponse.html","topicHref":"core/EchoHub.Core.DTOs.ErrorResponse.html","topicUid":"EchoHub.Core.DTOs.ErrorResponse","type":"Class"},{"name":"ExportedAttachmentDto","href":"core/EchoHub.Core.DTOs.ExportedAttachmentDto.html","topicHref":"core/EchoHub.Core.DTOs.ExportedAttachmentDto.html","topicUid":"EchoHub.Core.DTOs.ExportedAttachmentDto","type":"Class"},{"name":"ExportedMessageDto","href":"core/EchoHub.Core.DTOs.ExportedMessageDto.html","topicHref":"core/EchoHub.Core.DTOs.ExportedMessageDto.html","topicUid":"EchoHub.Core.DTOs.ExportedMessageDto","type":"Class"},{"name":"InviteDto","href":"core/EchoHub.Core.DTOs.InviteDto.html","topicHref":"core/EchoHub.Core.DTOs.InviteDto.html","topicUid":"EchoHub.Core.DTOs.InviteDto","type":"Class"},{"name":"JoinChannelResult","href":"core/EchoHub.Core.DTOs.JoinChannelResult.html","topicHref":"core/EchoHub.Core.DTOs.JoinChannelResult.html","topicUid":"EchoHub.Core.DTOs.JoinChannelResult","type":"Class"},{"name":"KickRequest","href":"core/EchoHub.Core.DTOs.KickRequest.html","topicHref":"core/EchoHub.Core.DTOs.KickRequest.html","topicUid":"EchoHub.Core.DTOs.KickRequest","type":"Class"},{"name":"LoginRequest","href":"core/EchoHub.Core.DTOs.LoginRequest.html","topicHref":"core/EchoHub.Core.DTOs.LoginRequest.html","topicUid":"EchoHub.Core.DTOs.LoginRequest","type":"Class"},{"name":"LoginResponse","href":"core/EchoHub.Core.DTOs.LoginResponse.html","topicHref":"core/EchoHub.Core.DTOs.LoginResponse.html","topicUid":"EchoHub.Core.DTOs.LoginResponse","type":"Class"},{"name":"MessageDto","href":"core/EchoHub.Core.DTOs.MessageDto.html","topicHref":"core/EchoHub.Core.DTOs.MessageDto.html","topicUid":"EchoHub.Core.DTOs.MessageDto","type":"Class"},{"name":"MuteRequest","href":"core/EchoHub.Core.DTOs.MuteRequest.html","topicHref":"core/EchoHub.Core.DTOs.MuteRequest.html","topicUid":"EchoHub.Core.DTOs.MuteRequest","type":"Class"},{"name":"PaginatedResponse","href":"core/EchoHub.Core.DTOs.PaginatedResponse-1.html","topicHref":"core/EchoHub.Core.DTOs.PaginatedResponse-1.html","topicUid":"EchoHub.Core.DTOs.PaginatedResponse`1","type":"Class"},{"name":"RefreshRequest","href":"core/EchoHub.Core.DTOs.RefreshRequest.html","topicHref":"core/EchoHub.Core.DTOs.RefreshRequest.html","topicUid":"EchoHub.Core.DTOs.RefreshRequest","type":"Class"},{"name":"RegisterRequest","href":"core/EchoHub.Core.DTOs.RegisterRequest.html","topicHref":"core/EchoHub.Core.DTOs.RegisterRequest.html","topicUid":"EchoHub.Core.DTOs.RegisterRequest","type":"Class"},{"name":"RekeyChannelRequest","href":"core/EchoHub.Core.DTOs.RekeyChannelRequest.html","topicHref":"core/EchoHub.Core.DTOs.RekeyChannelRequest.html","topicUid":"EchoHub.Core.DTOs.RekeyChannelRequest","type":"Class"},{"name":"ReplyRefDto","href":"core/EchoHub.Core.DTOs.ReplyRefDto.html","topicHref":"core/EchoHub.Core.DTOs.ReplyRefDto.html","topicUid":"EchoHub.Core.DTOs.ReplyRefDto","type":"Class"},{"name":"SendMessageRequest","href":"core/EchoHub.Core.DTOs.SendMessageRequest.html","topicHref":"core/EchoHub.Core.DTOs.SendMessageRequest.html","topicUid":"EchoHub.Core.DTOs.SendMessageRequest","type":"Class"},{"name":"SendUrlRequest","href":"core/EchoHub.Core.DTOs.SendUrlRequest.html","topicHref":"core/EchoHub.Core.DTOs.SendUrlRequest.html","topicUid":"EchoHub.Core.DTOs.SendUrlRequest","type":"Class"},{"name":"ServerStatusDto","href":"core/EchoHub.Core.DTOs.ServerStatusDto.html","topicHref":"core/EchoHub.Core.DTOs.ServerStatusDto.html","topicUid":"EchoHub.Core.DTOs.ServerStatusDto","type":"Class"},{"name":"UpdateProfileRequest","href":"core/EchoHub.Core.DTOs.UpdateProfileRequest.html","topicHref":"core/EchoHub.Core.DTOs.UpdateProfileRequest.html","topicUid":"EchoHub.Core.DTOs.UpdateProfileRequest","type":"Class"},{"name":"UpdateStatusRequest","href":"core/EchoHub.Core.DTOs.UpdateStatusRequest.html","topicHref":"core/EchoHub.Core.DTOs.UpdateStatusRequest.html","topicUid":"EchoHub.Core.DTOs.UpdateStatusRequest","type":"Class"},{"name":"UpdateTopicRequest","href":"core/EchoHub.Core.DTOs.UpdateTopicRequest.html","topicHref":"core/EchoHub.Core.DTOs.UpdateTopicRequest.html","topicUid":"EchoHub.Core.DTOs.UpdateTopicRequest","type":"Class"},{"name":"UserDataExportDto","href":"core/EchoHub.Core.DTOs.UserDataExportDto.html","topicHref":"core/EchoHub.Core.DTOs.UserDataExportDto.html","topicUid":"EchoHub.Core.DTOs.UserDataExportDto","type":"Class"},{"name":"UserDto","href":"core/EchoHub.Core.DTOs.UserDto.html","topicHref":"core/EchoHub.Core.DTOs.UserDto.html","topicUid":"EchoHub.Core.DTOs.UserDto","type":"Class"},{"name":"UserError","href":"core/EchoHub.Core.DTOs.UserError.html","topicHref":"core/EchoHub.Core.DTOs.UserError.html","topicUid":"EchoHub.Core.DTOs.UserError","type":"Enum"},{"name":"UserOperationResult","href":"core/EchoHub.Core.DTOs.UserOperationResult.html","topicHref":"core/EchoHub.Core.DTOs.UserOperationResult.html","topicUid":"EchoHub.Core.DTOs.UserOperationResult","type":"Class"},{"name":"UserPresenceDto","href":"core/EchoHub.Core.DTOs.UserPresenceDto.html","topicHref":"core/EchoHub.Core.DTOs.UserPresenceDto.html","topicUid":"EchoHub.Core.DTOs.UserPresenceDto","type":"Class"},{"name":"UserProfileDto","href":"core/EchoHub.Core.DTOs.UserProfileDto.html","topicHref":"core/EchoHub.Core.DTOs.UserProfileDto.html","topicUid":"EchoHub.Core.DTOs.UserProfileDto","type":"Class"}]},{"name":"EchoHub.Core.Models","href":"core/EchoHub.Core.Models.html","topicHref":"core/EchoHub.Core.Models.html","topicUid":"EchoHub.Core.Models","type":"Namespace","items":[{"name":"Attachment","href":"core/EchoHub.Core.Models.Attachment.html","topicHref":"core/EchoHub.Core.Models.Attachment.html","topicUid":"EchoHub.Core.Models.Attachment","type":"Class"},{"name":"AttachmentKind","href":"core/EchoHub.Core.Models.AttachmentKind.html","topicHref":"core/EchoHub.Core.Models.AttachmentKind.html","topicUid":"EchoHub.Core.Models.AttachmentKind","type":"Enum"},{"name":"Channel","href":"core/EchoHub.Core.Models.Channel.html","topicHref":"core/EchoHub.Core.Models.Channel.html","topicUid":"EchoHub.Core.Models.Channel","type":"Class"},{"name":"ChannelMembership","href":"core/EchoHub.Core.Models.ChannelMembership.html","topicHref":"core/EchoHub.Core.Models.ChannelMembership.html","topicUid":"EchoHub.Core.Models.ChannelMembership","type":"Class"},{"name":"InviteCode","href":"core/EchoHub.Core.Models.InviteCode.html","topicHref":"core/EchoHub.Core.Models.InviteCode.html","topicUid":"EchoHub.Core.Models.InviteCode","type":"Class"},{"name":"Message","href":"core/EchoHub.Core.Models.Message.html","topicHref":"core/EchoHub.Core.Models.Message.html","topicUid":"EchoHub.Core.Models.Message","type":"Class"},{"name":"MessageType","href":"core/EchoHub.Core.Models.MessageType.html","topicHref":"core/EchoHub.Core.Models.MessageType.html","topicUid":"EchoHub.Core.Models.MessageType","type":"Enum"},{"name":"RefreshToken","href":"core/EchoHub.Core.Models.RefreshToken.html","topicHref":"core/EchoHub.Core.Models.RefreshToken.html","topicUid":"EchoHub.Core.Models.RefreshToken","type":"Class"},{"name":"ServerRole","href":"core/EchoHub.Core.Models.ServerRole.html","topicHref":"core/EchoHub.Core.Models.ServerRole.html","topicUid":"EchoHub.Core.Models.ServerRole","type":"Enum"},{"name":"User","href":"core/EchoHub.Core.Models.User.html","topicHref":"core/EchoHub.Core.Models.User.html","topicUid":"EchoHub.Core.Models.User","type":"Class"},{"name":"UserStatus","href":"core/EchoHub.Core.Models.UserStatus.html","topicHref":"core/EchoHub.Core.Models.UserStatus.html","topicUid":"EchoHub.Core.Models.UserStatus","type":"Enum"}]},{"name":"EchoHub.Core.Security","href":"core/EchoHub.Core.Security.html","topicHref":"core/EchoHub.Core.Security.html","topicUid":"EchoHub.Core.Security","type":"Namespace","items":[{"name":"RoomCrypto","href":"core/EchoHub.Core.Security.RoomCrypto.html","topicHref":"core/EchoHub.Core.Security.RoomCrypto.html","topicUid":"EchoHub.Core.Security.RoomCrypto","type":"Class"},{"name":"RoomCrypto.DerivedKeys","href":"core/EchoHub.Core.Security.RoomCrypto.DerivedKeys.html","topicHref":"core/EchoHub.Core.Security.RoomCrypto.DerivedKeys.html","topicUid":"EchoHub.Core.Security.RoomCrypto.DerivedKeys","type":"Class"}]},{"name":"EchoHub.Core.Services","href":"core/EchoHub.Core.Services.html","topicHref":"core/EchoHub.Core.Services.html","topicUid":"EchoHub.Core.Services","type":"Namespace","items":[{"name":"AsciiBannerService","href":"core/EchoHub.Core.Services.AsciiBannerService.html","topicHref":"core/EchoHub.Core.Services.AsciiBannerService.html","topicUid":"EchoHub.Core.Services.AsciiBannerService","type":"Class"},{"name":"FileValidationHelper","href":"core/EchoHub.Core.Services.FileValidationHelper.html","topicHref":"core/EchoHub.Core.Services.FileValidationHelper.html","topicUid":"EchoHub.Core.Services.FileValidationHelper","type":"Class"},{"name":"ImageToAsciiService","href":"core/EchoHub.Core.Services.ImageToAsciiService.html","topicHref":"core/EchoHub.Core.Services.ImageToAsciiService.html","topicUid":"EchoHub.Core.Services.ImageToAsciiService","type":"Class"}]}]},{"name":"Articles","includedFrom":"~/api/core-articles/toc.yml","items":[{"name":"Overview","href":"core-articles/index.html","topicHref":"core-articles/index.html"}]}]},{"name":"Server","items":[{"name":"API Reference","includedFrom":"~/_api_meta/server/toc.yml","items":[{"name":"EchoHub.Server.Auth","href":"server/EchoHub.Server.Auth.html","topicHref":"server/EchoHub.Server.Auth.html","topicUid":"EchoHub.Server.Auth","type":"Namespace","items":[{"name":"JwtTokenService","href":"server/EchoHub.Server.Auth.JwtTokenService.html","topicHref":"server/EchoHub.Server.Auth.JwtTokenService.html","topicUid":"EchoHub.Server.Auth.JwtTokenService","type":"Class"}]},{"name":"EchoHub.Server.Config","href":"server/EchoHub.Server.Config.html","topicHref":"server/EchoHub.Server.Config.html","topicUid":"EchoHub.Server.Config","type":"Namespace","items":[{"name":"ServerLogsOptions","href":"server/EchoHub.Server.Config.ServerLogsOptions.html","topicHref":"server/EchoHub.Server.Config.ServerLogsOptions.html","topicUid":"EchoHub.Server.Config.ServerLogsOptions","type":"Class"},{"name":"SpamOptions","href":"server/EchoHub.Server.Config.SpamOptions.html","topicHref":"server/EchoHub.Server.Config.SpamOptions.html","topicUid":"EchoHub.Server.Config.SpamOptions","type":"Class"},{"name":"UploadLimits","href":"server/EchoHub.Server.Config.UploadLimits.html","topicHref":"server/EchoHub.Server.Config.UploadLimits.html","topicUid":"EchoHub.Server.Config.UploadLimits","type":"Class"}]},{"name":"EchoHub.Server.Controllers","href":"server/EchoHub.Server.Controllers.html","topicHref":"server/EchoHub.Server.Controllers.html","topicUid":"EchoHub.Server.Controllers","type":"Namespace","items":[{"name":"AuthController","href":"server/EchoHub.Server.Controllers.AuthController.html","topicHref":"server/EchoHub.Server.Controllers.AuthController.html","topicUid":"EchoHub.Server.Controllers.AuthController","type":"Class"},{"name":"ChannelsController","href":"server/EchoHub.Server.Controllers.ChannelsController.html","topicHref":"server/EchoHub.Server.Controllers.ChannelsController.html","topicUid":"EchoHub.Server.Controllers.ChannelsController","type":"Class"},{"name":"FilesController","href":"server/EchoHub.Server.Controllers.FilesController.html","topicHref":"server/EchoHub.Server.Controllers.FilesController.html","topicUid":"EchoHub.Server.Controllers.FilesController","type":"Class"},{"name":"InvitesController","href":"server/EchoHub.Server.Controllers.InvitesController.html","topicHref":"server/EchoHub.Server.Controllers.InvitesController.html","topicUid":"EchoHub.Server.Controllers.InvitesController","type":"Class"},{"name":"ModerationController","href":"server/EchoHub.Server.Controllers.ModerationController.html","topicHref":"server/EchoHub.Server.Controllers.ModerationController.html","topicUid":"EchoHub.Server.Controllers.ModerationController","type":"Class"},{"name":"ServerController","href":"server/EchoHub.Server.Controllers.ServerController.html","topicHref":"server/EchoHub.Server.Controllers.ServerController.html","topicUid":"EchoHub.Server.Controllers.ServerController","type":"Class"},{"name":"UsersController","href":"server/EchoHub.Server.Controllers.UsersController.html","topicHref":"server/EchoHub.Server.Controllers.UsersController.html","topicUid":"EchoHub.Server.Controllers.UsersController","type":"Class"}]},{"name":"EchoHub.Server.Data","href":"server/EchoHub.Server.Data.html","topicHref":"server/EchoHub.Server.Data.html","topicUid":"EchoHub.Server.Data","type":"Namespace","items":[{"name":"EchoHubDbContext","href":"server/EchoHub.Server.Data.EchoHubDbContext.html","topicHref":"server/EchoHub.Server.Data.EchoHubDbContext.html","topicUid":"EchoHub.Server.Data.EchoHubDbContext","type":"Class"}]},{"name":"EchoHub.Server.Data.Migrations","href":"server/EchoHub.Server.Data.Migrations.html","topicHref":"server/EchoHub.Server.Data.Migrations.html","topicUid":"EchoHub.Server.Data.Migrations","type":"Namespace","items":[{"name":"AddAttachmentFileSize","href":"server/EchoHub.Server.Data.Migrations.AddAttachmentFileSize.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddAttachmentFileSize.html","topicUid":"EchoHub.Server.Data.Migrations.AddAttachmentFileSize","type":"Class"},{"name":"AddChannelEncryptionEnvelope","href":"server/EchoHub.Server.Data.Migrations.AddChannelEncryptionEnvelope.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddChannelEncryptionEnvelope.html","topicUid":"EchoHub.Server.Data.Migrations.AddChannelEncryptionEnvelope","type":"Class"},{"name":"AddChannelIsPublic","href":"server/EchoHub.Server.Data.Migrations.AddChannelIsPublic.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddChannelIsPublic.html","topicUid":"EchoHub.Server.Data.Migrations.AddChannelIsPublic","type":"Class"},{"name":"AddChannelIsSystem","href":"server/EchoHub.Server.Data.Migrations.AddChannelIsSystem.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddChannelIsSystem.html","topicUid":"EchoHub.Server.Data.Migrations.AddChannelIsSystem","type":"Class"},{"name":"AddChannelMembership","href":"server/EchoHub.Server.Data.Migrations.AddChannelMembership.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddChannelMembership.html","topicUid":"EchoHub.Server.Data.Migrations.AddChannelMembership","type":"Class"},{"name":"AddChannelPasswordHash","href":"server/EchoHub.Server.Data.Migrations.AddChannelPasswordHash.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddChannelPasswordHash.html","topicUid":"EchoHub.Server.Data.Migrations.AddChannelPasswordHash","type":"Class"},{"name":"AddEncryptionSupport","href":"server/EchoHub.Server.Data.Migrations.AddEncryptionSupport.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddEncryptionSupport.html","topicUid":"EchoHub.Server.Data.Migrations.AddEncryptionSupport","type":"Class"},{"name":"AddInvitesAndReplies","href":"server/EchoHub.Server.Data.Migrations.AddInvitesAndReplies.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddInvitesAndReplies.html","topicUid":"EchoHub.Server.Data.Migrations.AddInvitesAndReplies","type":"Class"},{"name":"AddMessageAttachments","href":"server/EchoHub.Server.Data.Migrations.AddMessageAttachments.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddMessageAttachments.html","topicUid":"EchoHub.Server.Data.Migrations.AddMessageAttachments","type":"Class"},{"name":"AddMessageEmbed","href":"server/EchoHub.Server.Data.Migrations.AddMessageEmbed.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddMessageEmbed.html","topicUid":"EchoHub.Server.Data.Migrations.AddMessageEmbed","type":"Class"},{"name":"AddModerationRoles","href":"server/EchoHub.Server.Data.Migrations.AddModerationRoles.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddModerationRoles.html","topicUid":"EchoHub.Server.Data.Migrations.AddModerationRoles","type":"Class"},{"name":"InitialCreate","href":"server/EchoHub.Server.Data.Migrations.InitialCreate.html","topicHref":"server/EchoHub.Server.Data.Migrations.InitialCreate.html","topicUid":"EchoHub.Server.Data.Migrations.InitialCreate","type":"Class"}]},{"name":"EchoHub.Server.Hubs","href":"server/EchoHub.Server.Hubs.html","topicHref":"server/EchoHub.Server.Hubs.html","topicUid":"EchoHub.Server.Hubs","type":"Namespace","items":[{"name":"ChatHub","href":"server/EchoHub.Server.Hubs.ChatHub.html","topicHref":"server/EchoHub.Server.Hubs.ChatHub.html","topicUid":"EchoHub.Server.Hubs.ChatHub","type":"Class"}]},{"name":"EchoHub.Server.Services","href":"server/EchoHub.Server.Services.html","topicHref":"server/EchoHub.Server.Services.html","topicUid":"EchoHub.Server.Services","type":"Namespace","items":[{"name":"ChannelService","href":"server/EchoHub.Server.Services.ChannelService.html","topicHref":"server/EchoHub.Server.Services.ChannelService.html","topicUid":"EchoHub.Server.Services.ChannelService","type":"Class"},{"name":"ChatService","href":"server/EchoHub.Server.Services.ChatService.html","topicHref":"server/EchoHub.Server.Services.ChatService.html","topicUid":"EchoHub.Server.Services.ChatService","type":"Class"},{"name":"DirectoryClaimStore","href":"server/EchoHub.Server.Services.DirectoryClaimStore.html","topicHref":"server/EchoHub.Server.Services.DirectoryClaimStore.html","topicUid":"EchoHub.Server.Services.DirectoryClaimStore","type":"Class"},{"name":"FileCleanupService","href":"server/EchoHub.Server.Services.FileCleanupService.html","topicHref":"server/EchoHub.Server.Services.FileCleanupService.html","topicUid":"EchoHub.Server.Services.FileCleanupService","type":"Class"},{"name":"FileStorageService","href":"server/EchoHub.Server.Services.FileStorageService.html","topicHref":"server/EchoHub.Server.Services.FileStorageService.html","topicUid":"EchoHub.Server.Services.FileStorageService","type":"Class"},{"name":"LinkEmbedService","href":"server/EchoHub.Server.Services.LinkEmbedService.html","topicHref":"server/EchoHub.Server.Services.LinkEmbedService.html","topicUid":"EchoHub.Server.Services.LinkEmbedService","type":"Class"},{"name":"MessageEncryptionService","href":"server/EchoHub.Server.Services.MessageEncryptionService.html","topicHref":"server/EchoHub.Server.Services.MessageEncryptionService.html","topicUid":"EchoHub.Server.Services.MessageEncryptionService","type":"Class"},{"name":"MuteExpirationService","href":"server/EchoHub.Server.Services.MuteExpirationService.html","topicHref":"server/EchoHub.Server.Services.MuteExpirationService.html","topicUid":"EchoHub.Server.Services.MuteExpirationService","type":"Class"},{"name":"PresenceTracker","href":"server/EchoHub.Server.Services.PresenceTracker.html","topicHref":"server/EchoHub.Server.Services.PresenceTracker.html","topicUid":"EchoHub.Server.Services.PresenceTracker","type":"Class"},{"name":"RegistrationStatus","href":"server/EchoHub.Server.Services.RegistrationStatus.html","topicHref":"server/EchoHub.Server.Services.RegistrationStatus.html","topicUid":"EchoHub.Server.Services.RegistrationStatus","type":"Class"},{"name":"ServerDirectoryService","href":"server/EchoHub.Server.Services.ServerDirectoryService.html","topicHref":"server/EchoHub.Server.Services.ServerDirectoryService.html","topicUid":"EchoHub.Server.Services.ServerDirectoryService","type":"Class"},{"name":"SignalRBroadcaster","href":"server/EchoHub.Server.Services.SignalRBroadcaster.html","topicHref":"server/EchoHub.Server.Services.SignalRBroadcaster.html","topicUid":"EchoHub.Server.Services.SignalRBroadcaster","type":"Class"},{"name":"SpamGuard","href":"server/EchoHub.Server.Services.SpamGuard.html","topicHref":"server/EchoHub.Server.Services.SpamGuard.html","topicUid":"EchoHub.Server.Services.SpamGuard","type":"Class"},{"name":"SpamVerdict","href":"server/EchoHub.Server.Services.SpamVerdict.html","topicHref":"server/EchoHub.Server.Services.SpamVerdict.html","topicUid":"EchoHub.Server.Services.SpamVerdict","type":"Struct"},{"name":"SpamVerdictKind","href":"server/EchoHub.Server.Services.SpamVerdictKind.html","topicHref":"server/EchoHub.Server.Services.SpamVerdictKind.html","topicUid":"EchoHub.Server.Services.SpamVerdictKind","type":"Enum"},{"name":"UserService","href":"server/EchoHub.Server.Services.UserService.html","topicHref":"server/EchoHub.Server.Services.UserService.html","topicUid":"EchoHub.Server.Services.UserService","type":"Class"}]},{"name":"EchoHub.Server.Services.ServerLogs","href":"server/EchoHub.Server.Services.ServerLogs.html","topicHref":"server/EchoHub.Server.Services.ServerLogs.html","topicUid":"EchoHub.Server.Services.ServerLogs","type":"Namespace","items":[{"name":"LogBacklogEntry","href":"server/EchoHub.Server.Services.ServerLogs.LogBacklogEntry.html","topicHref":"server/EchoHub.Server.Services.ServerLogs.LogBacklogEntry.html","topicUid":"EchoHub.Server.Services.ServerLogs.LogBacklogEntry","type":"Class"},{"name":"ServerLogsService","href":"server/EchoHub.Server.Services.ServerLogs.ServerLogsService.html","topicHref":"server/EchoHub.Server.Services.ServerLogs.ServerLogsService.html","topicUid":"EchoHub.Server.Services.ServerLogs.ServerLogsService","type":"Class"},{"name":"ServerLogsSink","href":"server/EchoHub.Server.Services.ServerLogs.ServerLogsSink.html","topicHref":"server/EchoHub.Server.Services.ServerLogs.ServerLogsSink.html","topicUid":"EchoHub.Server.Services.ServerLogs.ServerLogsSink","type":"Class"},{"name":"ServerLogsStreamService","href":"server/EchoHub.Server.Services.ServerLogs.ServerLogsStreamService.html","topicHref":"server/EchoHub.Server.Services.ServerLogs.ServerLogsStreamService.html","topicUid":"EchoHub.Server.Services.ServerLogs.ServerLogsStreamService","type":"Class"}]},{"name":"EchoHub.Server.Setup","href":"server/EchoHub.Server.Setup.html","topicHref":"server/EchoHub.Server.Setup.html","topicUid":"EchoHub.Server.Setup","type":"Namespace","items":[{"name":"DataMigrationService","href":"server/EchoHub.Server.Setup.DataMigrationService.html","topicHref":"server/EchoHub.Server.Setup.DataMigrationService.html","topicUid":"EchoHub.Server.Setup.DataMigrationService","type":"Class"},{"name":"DatabaseSetup","href":"server/EchoHub.Server.Setup.DatabaseSetup.html","topicHref":"server/EchoHub.Server.Setup.DatabaseSetup.html","topicUid":"EchoHub.Server.Setup.DatabaseSetup","type":"Class"},{"name":"FirstRunSetup","href":"server/EchoHub.Server.Setup.FirstRunSetup.html","topicHref":"server/EchoHub.Server.Setup.FirstRunSetup.html","topicUid":"EchoHub.Server.Setup.FirstRunSetup","type":"Class"}]}]},{"name":"Articles","includedFrom":"~/api/server-articles/toc.yml","items":[{"name":"Overview","href":"server-articles/index.html","topicHref":"server-articles/index.html"}]}]},{"name":"Server.Irc","items":[{"name":"API Reference","includedFrom":"~/_api_meta/server-irc/toc.yml","items":[{"name":"EchoHub.Server.Irc","href":"server-irc/EchoHub.Server.Irc.html","topicHref":"server-irc/EchoHub.Server.Irc.html","topicUid":"EchoHub.Server.Irc","type":"Namespace","items":[{"name":"IrcBroadcaster","href":"server-irc/EchoHub.Server.Irc.IrcBroadcaster.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcBroadcaster.html","topicUid":"EchoHub.Server.Irc.IrcBroadcaster","type":"Class"},{"name":"IrcClientConnection","href":"server-irc/EchoHub.Server.Irc.IrcClientConnection.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcClientConnection.html","topicUid":"EchoHub.Server.Irc.IrcClientConnection","type":"Class"},{"name":"IrcCommandHandler","href":"server-irc/EchoHub.Server.Irc.IrcCommandHandler.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcCommandHandler.html","topicUid":"EchoHub.Server.Irc.IrcCommandHandler","type":"Class"},{"name":"IrcGatewayService","href":"server-irc/EchoHub.Server.Irc.IrcGatewayService.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcGatewayService.html","topicUid":"EchoHub.Server.Irc.IrcGatewayService","type":"Class"},{"name":"IrcMessage","href":"server-irc/EchoHub.Server.Irc.IrcMessage.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcMessage.html","topicUid":"EchoHub.Server.Irc.IrcMessage","type":"Class"},{"name":"IrcMessageFormatter","href":"server-irc/EchoHub.Server.Irc.IrcMessageFormatter.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcMessageFormatter.html","topicUid":"EchoHub.Server.Irc.IrcMessageFormatter","type":"Class"},{"name":"IrcNumericReply","href":"server-irc/EchoHub.Server.Irc.IrcNumericReply.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcNumericReply.html","topicUid":"EchoHub.Server.Irc.IrcNumericReply","type":"Class"},{"name":"IrcOptions","href":"server-irc/EchoHub.Server.Irc.IrcOptions.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcOptions.html","topicUid":"EchoHub.Server.Irc.IrcOptions","type":"Class"},{"name":"IrcServiceExtensions","href":"server-irc/EchoHub.Server.Irc.IrcServiceExtensions.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcServiceExtensions.html","topicUid":"EchoHub.Server.Irc.IrcServiceExtensions","type":"Class"}]}]}]}]} +{"items":[{"name":"Client","items":[{"name":"API Reference","includedFrom":"~/_api_meta/client/toc.yml","items":[{"name":"EchoHub.Client","href":"client/EchoHub.Client.html","topicHref":"client/EchoHub.Client.html","topicUid":"EchoHub.Client","type":"Namespace","items":[{"name":"AppOrchestrator","href":"client/EchoHub.Client.AppOrchestrator.html","topicHref":"client/EchoHub.Client.AppOrchestrator.html","topicUid":"EchoHub.Client.AppOrchestrator","type":"Class"}]},{"name":"EchoHub.Client.Commands","href":"client/EchoHub.Client.Commands.html","topicHref":"client/EchoHub.Client.Commands.html","topicUid":"EchoHub.Client.Commands","type":"Namespace","items":[{"name":"CommandHandler","href":"client/EchoHub.Client.Commands.CommandHandler.html","topicHref":"client/EchoHub.Client.Commands.CommandHandler.html","topicUid":"EchoHub.Client.Commands.CommandHandler","type":"Class"},{"name":"CommandResult","href":"client/EchoHub.Client.Commands.CommandResult.html","topicHref":"client/EchoHub.Client.Commands.CommandResult.html","topicUid":"EchoHub.Client.Commands.CommandResult","type":"Class"}]},{"name":"EchoHub.Client.Config","href":"client/EchoHub.Client.Config.html","topicHref":"client/EchoHub.Client.Config.html","topicUid":"EchoHub.Client.Config","type":"Namespace","items":[{"name":"AccountPreset","href":"client/EchoHub.Client.Config.AccountPreset.html","topicHref":"client/EchoHub.Client.Config.AccountPreset.html","topicUid":"EchoHub.Client.Config.AccountPreset","type":"Class"},{"name":"ClientConfig","href":"client/EchoHub.Client.Config.ClientConfig.html","topicHref":"client/EchoHub.Client.Config.ClientConfig.html","topicUid":"EchoHub.Client.Config.ClientConfig","type":"Class"},{"name":"ConfigManager","href":"client/EchoHub.Client.Config.ConfigManager.html","topicHref":"client/EchoHub.Client.Config.ConfigManager.html","topicUid":"EchoHub.Client.Config.ConfigManager","type":"Class"},{"name":"NotificationConfig","href":"client/EchoHub.Client.Config.NotificationConfig.html","topicHref":"client/EchoHub.Client.Config.NotificationConfig.html","topicUid":"EchoHub.Client.Config.NotificationConfig","type":"Class"},{"name":"SavedServer","href":"client/EchoHub.Client.Config.SavedServer.html","topicHref":"client/EchoHub.Client.Config.SavedServer.html","topicUid":"EchoHub.Client.Config.SavedServer","type":"Class"}]},{"name":"EchoHub.Client.Services","href":"client/EchoHub.Client.Services.html","topicHref":"client/EchoHub.Client.Services.html","topicUid":"EchoHub.Client.Services","type":"Namespace","items":[{"name":"ApiClient","href":"client/EchoHub.Client.Services.ApiClient.html","topicHref":"client/EchoHub.Client.Services.ApiClient.html","topicUid":"EchoHub.Client.Services.ApiClient","type":"Class"},{"name":"AsyncRunner","href":"client/EchoHub.Client.Services.AsyncRunner.html","topicHref":"client/EchoHub.Client.Services.AsyncRunner.html","topicUid":"EchoHub.Client.Services.AsyncRunner","type":"Class"},{"name":"AudioPlaybackService","href":"client/EchoHub.Client.Services.AudioPlaybackService.html","topicHref":"client/EchoHub.Client.Services.AudioPlaybackService.html","topicUid":"EchoHub.Client.Services.AudioPlaybackService","type":"Class"},{"name":"BackupInfo","href":"client/EchoHub.Client.Services.BackupInfo.html","topicHref":"client/EchoHub.Client.Services.BackupInfo.html","topicUid":"EchoHub.Client.Services.BackupInfo","type":"Class"},{"name":"ChannelPasswordRequiredException","href":"client/EchoHub.Client.Services.ChannelPasswordRequiredException.html","topicHref":"client/EchoHub.Client.Services.ChannelPasswordRequiredException.html","topicUid":"EchoHub.Client.Services.ChannelPasswordRequiredException","type":"Class"},{"name":"ClientEncryptionService","href":"client/EchoHub.Client.Services.ClientEncryptionService.html","topicHref":"client/EchoHub.Client.Services.ClientEncryptionService.html","topicUid":"EchoHub.Client.Services.ClientEncryptionService","type":"Class"},{"name":"ClipboardFiles","href":"client/EchoHub.Client.Services.ClipboardFiles.html","topicHref":"client/EchoHub.Client.Services.ClipboardFiles.html","topicUid":"EchoHub.Client.Services.ClipboardFiles","type":"Class"},{"name":"ClipboardImage","href":"client/EchoHub.Client.Services.ClipboardImage.html","topicHref":"client/EchoHub.Client.Services.ClipboardImage.html","topicUid":"EchoHub.Client.Services.ClipboardImage","type":"Class"},{"name":"EchoHubConnection","href":"client/EchoHub.Client.Services.EchoHubConnection.html","topicHref":"client/EchoHub.Client.Services.EchoHubConnection.html","topicUid":"EchoHub.Client.Services.EchoHubConnection","type":"Class"},{"name":"FolderPickResult","href":"client/EchoHub.Client.Services.FolderPickResult.html","topicHref":"client/EchoHub.Client.Services.FolderPickResult.html","topicUid":"EchoHub.Client.Services.FolderPickResult","type":"Class"},{"name":"JoinOutcome","href":"client/EchoHub.Client.Services.JoinOutcome.html","topicHref":"client/EchoHub.Client.Services.JoinOutcome.html","topicUid":"EchoHub.Client.Services.JoinOutcome","type":"Class"},{"name":"NativeFolderPicker","href":"client/EchoHub.Client.Services.NativeFolderPicker.html","topicHref":"client/EchoHub.Client.Services.NativeFolderPicker.html","topicUid":"EchoHub.Client.Services.NativeFolderPicker","type":"Class"},{"name":"NotificationSoundService","href":"client/EchoHub.Client.Services.NotificationSoundService.html","topicHref":"client/EchoHub.Client.Services.NotificationSoundService.html","topicUid":"EchoHub.Client.Services.NotificationSoundService","type":"Class"},{"name":"OutgoingAttachment","href":"client/EchoHub.Client.Services.OutgoingAttachment.html","topicHref":"client/EchoHub.Client.Services.OutgoingAttachment.html","topicUid":"EchoHub.Client.Services.OutgoingAttachment","type":"Class"},{"name":"PathSetup","href":"client/EchoHub.Client.Services.PathSetup.html","topicHref":"client/EchoHub.Client.Services.PathSetup.html","topicUid":"EchoHub.Client.Services.PathSetup","type":"Class"},{"name":"PickerOutcome","href":"client/EchoHub.Client.Services.PickerOutcome.html","topicHref":"client/EchoHub.Client.Services.PickerOutcome.html","topicUid":"EchoHub.Client.Services.PickerOutcome","type":"Enum"},{"name":"RoomKeyProtector","href":"client/EchoHub.Client.Services.RoomKeyProtector.html","topicHref":"client/EchoHub.Client.Services.RoomKeyProtector.html","topicUid":"EchoHub.Client.Services.RoomKeyProtector","type":"Class"},{"name":"RoomKeyStore","href":"client/EchoHub.Client.Services.RoomKeyStore.html","topicHref":"client/EchoHub.Client.Services.RoomKeyStore.html","topicUid":"EchoHub.Client.Services.RoomKeyStore","type":"Class"},{"name":"RoomLockedException","href":"client/EchoHub.Client.Services.RoomLockedException.html","topicHref":"client/EchoHub.Client.Services.RoomLockedException.html","topicUid":"EchoHub.Client.Services.RoomLockedException","type":"Class"},{"name":"UpdateBackupService","href":"client/EchoHub.Client.Services.UpdateBackupService.html","topicHref":"client/EchoHub.Client.Services.UpdateBackupService.html","topicUid":"EchoHub.Client.Services.UpdateBackupService","type":"Class"},{"name":"UpdateChecker","href":"client/EchoHub.Client.Services.UpdateChecker.html","topicHref":"client/EchoHub.Client.Services.UpdateChecker.html","topicUid":"EchoHub.Client.Services.UpdateChecker","type":"Class"}]},{"name":"EchoHub.Client.Themes","href":"client/EchoHub.Client.Themes.html","topicHref":"client/EchoHub.Client.Themes.html","topicUid":"EchoHub.Client.Themes","type":"Namespace","items":[{"name":"Theme","href":"client/EchoHub.Client.Themes.Theme.html","topicHref":"client/EchoHub.Client.Themes.Theme.html","topicUid":"EchoHub.Client.Themes.Theme","type":"Class"},{"name":"ThemeColors","href":"client/EchoHub.Client.Themes.ThemeColors.html","topicHref":"client/EchoHub.Client.Themes.ThemeColors.html","topicUid":"EchoHub.Client.Themes.ThemeColors","type":"Class"},{"name":"ThemeManager","href":"client/EchoHub.Client.Themes.ThemeManager.html","topicHref":"client/EchoHub.Client.Themes.ThemeManager.html","topicUid":"EchoHub.Client.Themes.ThemeManager","type":"Class"}]},{"name":"EchoHub.Client.UI","href":"client/EchoHub.Client.UI.html","topicHref":"client/EchoHub.Client.UI.html","topicUid":"EchoHub.Client.UI","type":"Namespace","items":[{"name":"MainWindow","href":"client/EchoHub.Client.UI.MainWindow.html","topicHref":"client/EchoHub.Client.UI.MainWindow.html","topicUid":"EchoHub.Client.UI.MainWindow","type":"Class"}]},{"name":"EchoHub.Client.UI.Chat","href":"client/EchoHub.Client.UI.Chat.html","topicHref":"client/EchoHub.Client.UI.Chat.html","topicUid":"EchoHub.Client.UI.Chat","type":"Namespace","items":[{"name":"AttachmentAction","href":"client/EchoHub.Client.UI.Chat.AttachmentAction.html","topicHref":"client/EchoHub.Client.UI.Chat.AttachmentAction.html","topicUid":"EchoHub.Client.UI.Chat.AttachmentAction","type":"Enum"},{"name":"AttachmentActionSpan","href":"client/EchoHub.Client.UI.Chat.AttachmentActionSpan.html","topicHref":"client/EchoHub.Client.UI.Chat.AttachmentActionSpan.html","topicUid":"EchoHub.Client.UI.Chat.AttachmentActionSpan","type":"Struct"},{"name":"ChatColors","href":"client/EchoHub.Client.UI.Chat.ChatColors.html","topicHref":"client/EchoHub.Client.UI.Chat.ChatColors.html","topicUid":"EchoHub.Client.UI.Chat.ChatColors","type":"Class"},{"name":"ChatLine","href":"client/EchoHub.Client.UI.Chat.ChatLine.html","topicHref":"client/EchoHub.Client.UI.Chat.ChatLine.html","topicUid":"EchoHub.Client.UI.Chat.ChatLine","type":"Class"},{"name":"ChatListSource","href":"client/EchoHub.Client.UI.Chat.ChatListSource.html","topicHref":"client/EchoHub.Client.UI.Chat.ChatListSource.html","topicUid":"EchoHub.Client.UI.Chat.ChatListSource","type":"Class"},{"name":"ChatMessageManager","href":"client/EchoHub.Client.UI.Chat.ChatMessageManager.html","topicHref":"client/EchoHub.Client.UI.Chat.ChatMessageManager.html","topicUid":"EchoHub.Client.UI.Chat.ChatMessageManager","type":"Class"},{"name":"ChatSegment","href":"client/EchoHub.Client.UI.Chat.ChatSegment.html","topicHref":"client/EchoHub.Client.UI.Chat.ChatSegment.html","topicUid":"EchoHub.Client.UI.Chat.ChatSegment","type":"Class"}]},{"name":"EchoHub.Client.UI.Dialogs","href":"client/EchoHub.Client.UI.Dialogs.html","topicHref":"client/EchoHub.Client.UI.Dialogs.html","topicUid":"EchoHub.Client.UI.Dialogs","type":"Namespace","items":[{"name":"AudioPlayerDialog","href":"client/EchoHub.Client.UI.Dialogs.AudioPlayerDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.AudioPlayerDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.AudioPlayerDialog","type":"Class"},{"name":"ChannelPasswordDialog","href":"client/EchoHub.Client.UI.Dialogs.ChannelPasswordDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ChannelPasswordDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.ChannelPasswordDialog","type":"Class"},{"name":"ConnectDialog","href":"client/EchoHub.Client.UI.Dialogs.ConnectDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ConnectDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.ConnectDialog","type":"Class"},{"name":"ConnectDialogResult","href":"client/EchoHub.Client.UI.Dialogs.ConnectDialogResult.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ConnectDialogResult.html","topicUid":"EchoHub.Client.UI.Dialogs.ConnectDialogResult","type":"Class"},{"name":"CreateChannelDialog","href":"client/EchoHub.Client.UI.Dialogs.CreateChannelDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.CreateChannelDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.CreateChannelDialog","type":"Class"},{"name":"CreateChannelResult","href":"client/EchoHub.Client.UI.Dialogs.CreateChannelResult.html","topicHref":"client/EchoHub.Client.UI.Dialogs.CreateChannelResult.html","topicUid":"EchoHub.Client.UI.Dialogs.CreateChannelResult","type":"Class"},{"name":"ProfileAction","href":"client/EchoHub.Client.UI.Dialogs.ProfileAction.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ProfileAction.html","topicUid":"EchoHub.Client.UI.Dialogs.ProfileAction","type":"Enum"},{"name":"ProfileEditDialog","href":"client/EchoHub.Client.UI.Dialogs.ProfileEditDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ProfileEditDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.ProfileEditDialog","type":"Class"},{"name":"ProfileEditResult","href":"client/EchoHub.Client.UI.Dialogs.ProfileEditResult.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ProfileEditResult.html","topicUid":"EchoHub.Client.UI.Dialogs.ProfileEditResult","type":"Class"},{"name":"ProfileViewDialog","href":"client/EchoHub.Client.UI.Dialogs.ProfileViewDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ProfileViewDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.ProfileViewDialog","type":"Class"},{"name":"SearchDialog","href":"client/EchoHub.Client.UI.Dialogs.SearchDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.SearchDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.SearchDialog","type":"Class"},{"name":"SearchResult","href":"client/EchoHub.Client.UI.Dialogs.SearchResult.html","topicHref":"client/EchoHub.Client.UI.Dialogs.SearchResult.html","topicUid":"EchoHub.Client.UI.Dialogs.SearchResult","type":"Class"},{"name":"SearchResultType","href":"client/EchoHub.Client.UI.Dialogs.SearchResultType.html","topicHref":"client/EchoHub.Client.UI.Dialogs.SearchResultType.html","topicUid":"EchoHub.Client.UI.Dialogs.SearchResultType","type":"Enum"},{"name":"StatusDialog","href":"client/EchoHub.Client.UI.Dialogs.StatusDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.StatusDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.StatusDialog","type":"Class"},{"name":"StatusDialogResult","href":"client/EchoHub.Client.UI.Dialogs.StatusDialogResult.html","topicHref":"client/EchoHub.Client.UI.Dialogs.StatusDialogResult.html","topicUid":"EchoHub.Client.UI.Dialogs.StatusDialogResult","type":"Class"},{"name":"UpdateConfirmDialog","href":"client/EchoHub.Client.UI.Dialogs.UpdateConfirmDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.UpdateConfirmDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.UpdateConfirmDialog","type":"Class"}]},{"name":"EchoHub.Client.UI.Helpers","href":"client/EchoHub.Client.UI.Helpers.html","topicHref":"client/EchoHub.Client.UI.Helpers.html","topicUid":"EchoHub.Client.UI.Helpers","type":"Namespace","items":[{"name":"DroppedFileParser","href":"client/EchoHub.Client.UI.Helpers.DroppedFileParser.html","topicHref":"client/EchoHub.Client.UI.Helpers.DroppedFileParser.html","topicUid":"EchoHub.Client.UI.Helpers.DroppedFileParser","type":"Class"},{"name":"EmojiHelper","href":"client/EchoHub.Client.UI.Helpers.EmojiHelper.html","topicHref":"client/EchoHub.Client.UI.Helpers.EmojiHelper.html","topicUid":"EchoHub.Client.UI.Helpers.EmojiHelper","type":"Class"},{"name":"HexColorHelper","href":"client/EchoHub.Client.UI.Helpers.HexColorHelper.html","topicHref":"client/EchoHub.Client.UI.Helpers.HexColorHelper.html","topicUid":"EchoHub.Client.UI.Helpers.HexColorHelper","type":"Class"},{"name":"NickColorHelper","href":"client/EchoHub.Client.UI.Helpers.NickColorHelper.html","topicHref":"client/EchoHub.Client.UI.Helpers.NickColorHelper.html","topicUid":"EchoHub.Client.UI.Helpers.NickColorHelper","type":"Class"}]},{"name":"EchoHub.Client.UI.ListSources","href":"client/EchoHub.Client.UI.ListSources.html","topicHref":"client/EchoHub.Client.UI.ListSources.html","topicUid":"EchoHub.Client.UI.ListSources","type":"Namespace","items":[{"name":"ChannelListSource","href":"client/EchoHub.Client.UI.ListSources.ChannelListSource.html","topicHref":"client/EchoHub.Client.UI.ListSources.ChannelListSource.html","topicUid":"EchoHub.Client.UI.ListSources.ChannelListSource","type":"Class"},{"name":"SearchListSource","href":"client/EchoHub.Client.UI.ListSources.SearchListSource.html","topicHref":"client/EchoHub.Client.UI.ListSources.SearchListSource.html","topicUid":"EchoHub.Client.UI.ListSources.SearchListSource","type":"Class"},{"name":"UserListSource","href":"client/EchoHub.Client.UI.ListSources.UserListSource.html","topicHref":"client/EchoHub.Client.UI.ListSources.UserListSource.html","topicUid":"EchoHub.Client.UI.ListSources.UserListSource","type":"Class"}]}]},{"name":"Articles","includedFrom":"~/api/client-articles/toc.yml","items":[{"name":"Overview","href":"client-articles/index.html","topicHref":"client-articles/index.html"}]}]},{"name":"Core","items":[{"name":"API Reference","includedFrom":"~/_api_meta/core/toc.yml","items":[{"name":"EchoHub.Core.Constants","href":"core/EchoHub.Core.Constants.html","topicHref":"core/EchoHub.Core.Constants.html","topicUid":"EchoHub.Core.Constants","type":"Namespace","items":[{"name":"HubConstants","href":"core/EchoHub.Core.Constants.HubConstants.html","topicHref":"core/EchoHub.Core.Constants.HubConstants.html","topicUid":"EchoHub.Core.Constants.HubConstants","type":"Class"},{"name":"MessageConventions","href":"core/EchoHub.Core.Constants.MessageConventions.html","topicHref":"core/EchoHub.Core.Constants.MessageConventions.html","topicUid":"EchoHub.Core.Constants.MessageConventions","type":"Class"},{"name":"ValidationConstants","href":"core/EchoHub.Core.Constants.ValidationConstants.html","topicHref":"core/EchoHub.Core.Constants.ValidationConstants.html","topicUid":"EchoHub.Core.Constants.ValidationConstants","type":"Class"}]},{"name":"EchoHub.Core.Contracts","href":"core/EchoHub.Core.Contracts.html","topicHref":"core/EchoHub.Core.Contracts.html","topicUid":"EchoHub.Core.Contracts","type":"Namespace","items":[{"name":"ChannelListItem","href":"core/EchoHub.Core.Contracts.ChannelListItem.html","topicHref":"core/EchoHub.Core.Contracts.ChannelListItem.html","topicUid":"EchoHub.Core.Contracts.ChannelListItem","type":"Class"},{"name":"IChannelService","href":"core/EchoHub.Core.Contracts.IChannelService.html","topicHref":"core/EchoHub.Core.Contracts.IChannelService.html","topicUid":"EchoHub.Core.Contracts.IChannelService","type":"Interface"},{"name":"IChatBroadcaster","href":"core/EchoHub.Core.Contracts.IChatBroadcaster.html","topicHref":"core/EchoHub.Core.Contracts.IChatBroadcaster.html","topicUid":"EchoHub.Core.Contracts.IChatBroadcaster","type":"Interface"},{"name":"IChatService","href":"core/EchoHub.Core.Contracts.IChatService.html","topicHref":"core/EchoHub.Core.Contracts.IChatService.html","topicUid":"EchoHub.Core.Contracts.IChatService","type":"Interface"},{"name":"IEchoHubClient","href":"core/EchoHub.Core.Contracts.IEchoHubClient.html","topicHref":"core/EchoHub.Core.Contracts.IEchoHubClient.html","topicUid":"EchoHub.Core.Contracts.IEchoHubClient","type":"Interface"},{"name":"IMessageEncryptionService","href":"core/EchoHub.Core.Contracts.IMessageEncryptionService.html","topicHref":"core/EchoHub.Core.Contracts.IMessageEncryptionService.html","topicUid":"EchoHub.Core.Contracts.IMessageEncryptionService","type":"Interface"},{"name":"IUserService","href":"core/EchoHub.Core.Contracts.IUserService.html","topicHref":"core/EchoHub.Core.Contracts.IUserService.html","topicUid":"EchoHub.Core.Contracts.IUserService","type":"Interface"}]},{"name":"EchoHub.Core.DTOs","href":"core/EchoHub.Core.DTOs.html","topicHref":"core/EchoHub.Core.DTOs.html","topicUid":"EchoHub.Core.DTOs","type":"Namespace","items":[{"name":"ApiResponse","href":"core/EchoHub.Core.DTOs.ApiResponse.html","topicHref":"core/EchoHub.Core.DTOs.ApiResponse.html","topicUid":"EchoHub.Core.DTOs.ApiResponse","type":"Class"},{"name":"ApiResponse","href":"core/EchoHub.Core.DTOs.ApiResponse-1.html","topicHref":"core/EchoHub.Core.DTOs.ApiResponse-1.html","topicUid":"EchoHub.Core.DTOs.ApiResponse`1","type":"Class"},{"name":"AssignRoleRequest","href":"core/EchoHub.Core.DTOs.AssignRoleRequest.html","topicHref":"core/EchoHub.Core.DTOs.AssignRoleRequest.html","topicUid":"EchoHub.Core.DTOs.AssignRoleRequest","type":"Class"},{"name":"AttachmentDto","href":"core/EchoHub.Core.DTOs.AttachmentDto.html","topicHref":"core/EchoHub.Core.DTOs.AttachmentDto.html","topicUid":"EchoHub.Core.DTOs.AttachmentDto","type":"Class"},{"name":"AvatarUploadResponse","href":"core/EchoHub.Core.DTOs.AvatarUploadResponse.html","topicHref":"core/EchoHub.Core.DTOs.AvatarUploadResponse.html","topicUid":"EchoHub.Core.DTOs.AvatarUploadResponse","type":"Class"},{"name":"BanRequest","href":"core/EchoHub.Core.DTOs.BanRequest.html","topicHref":"core/EchoHub.Core.DTOs.BanRequest.html","topicUid":"EchoHub.Core.DTOs.BanRequest","type":"Class"},{"name":"ChannelCryptoDto","href":"core/EchoHub.Core.DTOs.ChannelCryptoDto.html","topicHref":"core/EchoHub.Core.DTOs.ChannelCryptoDto.html","topicUid":"EchoHub.Core.DTOs.ChannelCryptoDto","type":"Class"},{"name":"ChannelDto","href":"core/EchoHub.Core.DTOs.ChannelDto.html","topicHref":"core/EchoHub.Core.DTOs.ChannelDto.html","topicUid":"EchoHub.Core.DTOs.ChannelDto","type":"Class"},{"name":"ChannelError","href":"core/EchoHub.Core.DTOs.ChannelError.html","topicHref":"core/EchoHub.Core.DTOs.ChannelError.html","topicUid":"EchoHub.Core.DTOs.ChannelError","type":"Enum"},{"name":"ChannelMetaDto","href":"core/EchoHub.Core.DTOs.ChannelMetaDto.html","topicHref":"core/EchoHub.Core.DTOs.ChannelMetaDto.html","topicUid":"EchoHub.Core.DTOs.ChannelMetaDto","type":"Class"},{"name":"ChannelOperationResult","href":"core/EchoHub.Core.DTOs.ChannelOperationResult.html","topicHref":"core/EchoHub.Core.DTOs.ChannelOperationResult.html","topicUid":"EchoHub.Core.DTOs.ChannelOperationResult","type":"Class"},{"name":"CreateChannelRequest","href":"core/EchoHub.Core.DTOs.CreateChannelRequest.html","topicHref":"core/EchoHub.Core.DTOs.CreateChannelRequest.html","topicUid":"EchoHub.Core.DTOs.CreateChannelRequest","type":"Class"},{"name":"CreateInviteRequest","href":"core/EchoHub.Core.DTOs.CreateInviteRequest.html","topicHref":"core/EchoHub.Core.DTOs.CreateInviteRequest.html","topicUid":"EchoHub.Core.DTOs.CreateInviteRequest","type":"Class"},{"name":"DeleteAccountRequest","href":"core/EchoHub.Core.DTOs.DeleteAccountRequest.html","topicHref":"core/EchoHub.Core.DTOs.DeleteAccountRequest.html","topicUid":"EchoHub.Core.DTOs.DeleteAccountRequest","type":"Class"},{"name":"EmbedDto","href":"core/EchoHub.Core.DTOs.EmbedDto.html","topicHref":"core/EchoHub.Core.DTOs.EmbedDto.html","topicUid":"EchoHub.Core.DTOs.EmbedDto","type":"Class"},{"name":"EncryptionKeyResponse","href":"core/EchoHub.Core.DTOs.EncryptionKeyResponse.html","topicHref":"core/EchoHub.Core.DTOs.EncryptionKeyResponse.html","topicUid":"EchoHub.Core.DTOs.EncryptionKeyResponse","type":"Class"},{"name":"ErrorResponse","href":"core/EchoHub.Core.DTOs.ErrorResponse.html","topicHref":"core/EchoHub.Core.DTOs.ErrorResponse.html","topicUid":"EchoHub.Core.DTOs.ErrorResponse","type":"Class"},{"name":"ExportedAttachmentDto","href":"core/EchoHub.Core.DTOs.ExportedAttachmentDto.html","topicHref":"core/EchoHub.Core.DTOs.ExportedAttachmentDto.html","topicUid":"EchoHub.Core.DTOs.ExportedAttachmentDto","type":"Class"},{"name":"ExportedMessageDto","href":"core/EchoHub.Core.DTOs.ExportedMessageDto.html","topicHref":"core/EchoHub.Core.DTOs.ExportedMessageDto.html","topicUid":"EchoHub.Core.DTOs.ExportedMessageDto","type":"Class"},{"name":"InviteDto","href":"core/EchoHub.Core.DTOs.InviteDto.html","topicHref":"core/EchoHub.Core.DTOs.InviteDto.html","topicUid":"EchoHub.Core.DTOs.InviteDto","type":"Class"},{"name":"JoinChannelResult","href":"core/EchoHub.Core.DTOs.JoinChannelResult.html","topicHref":"core/EchoHub.Core.DTOs.JoinChannelResult.html","topicUid":"EchoHub.Core.DTOs.JoinChannelResult","type":"Class"},{"name":"KickRequest","href":"core/EchoHub.Core.DTOs.KickRequest.html","topicHref":"core/EchoHub.Core.DTOs.KickRequest.html","topicUid":"EchoHub.Core.DTOs.KickRequest","type":"Class"},{"name":"LoginRequest","href":"core/EchoHub.Core.DTOs.LoginRequest.html","topicHref":"core/EchoHub.Core.DTOs.LoginRequest.html","topicUid":"EchoHub.Core.DTOs.LoginRequest","type":"Class"},{"name":"LoginResponse","href":"core/EchoHub.Core.DTOs.LoginResponse.html","topicHref":"core/EchoHub.Core.DTOs.LoginResponse.html","topicUid":"EchoHub.Core.DTOs.LoginResponse","type":"Class"},{"name":"MessageDto","href":"core/EchoHub.Core.DTOs.MessageDto.html","topicHref":"core/EchoHub.Core.DTOs.MessageDto.html","topicUid":"EchoHub.Core.DTOs.MessageDto","type":"Class"},{"name":"MuteRequest","href":"core/EchoHub.Core.DTOs.MuteRequest.html","topicHref":"core/EchoHub.Core.DTOs.MuteRequest.html","topicUid":"EchoHub.Core.DTOs.MuteRequest","type":"Class"},{"name":"PaginatedResponse","href":"core/EchoHub.Core.DTOs.PaginatedResponse-1.html","topicHref":"core/EchoHub.Core.DTOs.PaginatedResponse-1.html","topicUid":"EchoHub.Core.DTOs.PaginatedResponse`1","type":"Class"},{"name":"RefreshRequest","href":"core/EchoHub.Core.DTOs.RefreshRequest.html","topicHref":"core/EchoHub.Core.DTOs.RefreshRequest.html","topicUid":"EchoHub.Core.DTOs.RefreshRequest","type":"Class"},{"name":"RegisterRequest","href":"core/EchoHub.Core.DTOs.RegisterRequest.html","topicHref":"core/EchoHub.Core.DTOs.RegisterRequest.html","topicUid":"EchoHub.Core.DTOs.RegisterRequest","type":"Class"},{"name":"RekeyChannelRequest","href":"core/EchoHub.Core.DTOs.RekeyChannelRequest.html","topicHref":"core/EchoHub.Core.DTOs.RekeyChannelRequest.html","topicUid":"EchoHub.Core.DTOs.RekeyChannelRequest","type":"Class"},{"name":"ReplyRefDto","href":"core/EchoHub.Core.DTOs.ReplyRefDto.html","topicHref":"core/EchoHub.Core.DTOs.ReplyRefDto.html","topicUid":"EchoHub.Core.DTOs.ReplyRefDto","type":"Class"},{"name":"SendMessageRequest","href":"core/EchoHub.Core.DTOs.SendMessageRequest.html","topicHref":"core/EchoHub.Core.DTOs.SendMessageRequest.html","topicUid":"EchoHub.Core.DTOs.SendMessageRequest","type":"Class"},{"name":"SendUrlRequest","href":"core/EchoHub.Core.DTOs.SendUrlRequest.html","topicHref":"core/EchoHub.Core.DTOs.SendUrlRequest.html","topicUid":"EchoHub.Core.DTOs.SendUrlRequest","type":"Class"},{"name":"ServerStatusDto","href":"core/EchoHub.Core.DTOs.ServerStatusDto.html","topicHref":"core/EchoHub.Core.DTOs.ServerStatusDto.html","topicUid":"EchoHub.Core.DTOs.ServerStatusDto","type":"Class"},{"name":"UpdateProfileRequest","href":"core/EchoHub.Core.DTOs.UpdateProfileRequest.html","topicHref":"core/EchoHub.Core.DTOs.UpdateProfileRequest.html","topicUid":"EchoHub.Core.DTOs.UpdateProfileRequest","type":"Class"},{"name":"UpdateStatusRequest","href":"core/EchoHub.Core.DTOs.UpdateStatusRequest.html","topicHref":"core/EchoHub.Core.DTOs.UpdateStatusRequest.html","topicUid":"EchoHub.Core.DTOs.UpdateStatusRequest","type":"Class"},{"name":"UpdateTopicRequest","href":"core/EchoHub.Core.DTOs.UpdateTopicRequest.html","topicHref":"core/EchoHub.Core.DTOs.UpdateTopicRequest.html","topicUid":"EchoHub.Core.DTOs.UpdateTopicRequest","type":"Class"},{"name":"UserDataExportDto","href":"core/EchoHub.Core.DTOs.UserDataExportDto.html","topicHref":"core/EchoHub.Core.DTOs.UserDataExportDto.html","topicUid":"EchoHub.Core.DTOs.UserDataExportDto","type":"Class"},{"name":"UserDto","href":"core/EchoHub.Core.DTOs.UserDto.html","topicHref":"core/EchoHub.Core.DTOs.UserDto.html","topicUid":"EchoHub.Core.DTOs.UserDto","type":"Class"},{"name":"UserError","href":"core/EchoHub.Core.DTOs.UserError.html","topicHref":"core/EchoHub.Core.DTOs.UserError.html","topicUid":"EchoHub.Core.DTOs.UserError","type":"Enum"},{"name":"UserOperationResult","href":"core/EchoHub.Core.DTOs.UserOperationResult.html","topicHref":"core/EchoHub.Core.DTOs.UserOperationResult.html","topicUid":"EchoHub.Core.DTOs.UserOperationResult","type":"Class"},{"name":"UserPresenceDto","href":"core/EchoHub.Core.DTOs.UserPresenceDto.html","topicHref":"core/EchoHub.Core.DTOs.UserPresenceDto.html","topicUid":"EchoHub.Core.DTOs.UserPresenceDto","type":"Class"},{"name":"UserProfileDto","href":"core/EchoHub.Core.DTOs.UserProfileDto.html","topicHref":"core/EchoHub.Core.DTOs.UserProfileDto.html","topicUid":"EchoHub.Core.DTOs.UserProfileDto","type":"Class"}]},{"name":"EchoHub.Core.Models","href":"core/EchoHub.Core.Models.html","topicHref":"core/EchoHub.Core.Models.html","topicUid":"EchoHub.Core.Models","type":"Namespace","items":[{"name":"Attachment","href":"core/EchoHub.Core.Models.Attachment.html","topicHref":"core/EchoHub.Core.Models.Attachment.html","topicUid":"EchoHub.Core.Models.Attachment","type":"Class"},{"name":"AttachmentKind","href":"core/EchoHub.Core.Models.AttachmentKind.html","topicHref":"core/EchoHub.Core.Models.AttachmentKind.html","topicUid":"EchoHub.Core.Models.AttachmentKind","type":"Enum"},{"name":"Channel","href":"core/EchoHub.Core.Models.Channel.html","topicHref":"core/EchoHub.Core.Models.Channel.html","topicUid":"EchoHub.Core.Models.Channel","type":"Class"},{"name":"ChannelMembership","href":"core/EchoHub.Core.Models.ChannelMembership.html","topicHref":"core/EchoHub.Core.Models.ChannelMembership.html","topicUid":"EchoHub.Core.Models.ChannelMembership","type":"Class"},{"name":"InviteCode","href":"core/EchoHub.Core.Models.InviteCode.html","topicHref":"core/EchoHub.Core.Models.InviteCode.html","topicUid":"EchoHub.Core.Models.InviteCode","type":"Class"},{"name":"Message","href":"core/EchoHub.Core.Models.Message.html","topicHref":"core/EchoHub.Core.Models.Message.html","topicUid":"EchoHub.Core.Models.Message","type":"Class"},{"name":"MessageType","href":"core/EchoHub.Core.Models.MessageType.html","topicHref":"core/EchoHub.Core.Models.MessageType.html","topicUid":"EchoHub.Core.Models.MessageType","type":"Enum"},{"name":"RefreshToken","href":"core/EchoHub.Core.Models.RefreshToken.html","topicHref":"core/EchoHub.Core.Models.RefreshToken.html","topicUid":"EchoHub.Core.Models.RefreshToken","type":"Class"},{"name":"ServerRole","href":"core/EchoHub.Core.Models.ServerRole.html","topicHref":"core/EchoHub.Core.Models.ServerRole.html","topicUid":"EchoHub.Core.Models.ServerRole","type":"Enum"},{"name":"ServerStatsReport","href":"core/EchoHub.Core.Models.ServerStatsReport.html","topicHref":"core/EchoHub.Core.Models.ServerStatsReport.html","topicUid":"EchoHub.Core.Models.ServerStatsReport","type":"Class"},{"name":"User","href":"core/EchoHub.Core.Models.User.html","topicHref":"core/EchoHub.Core.Models.User.html","topicUid":"EchoHub.Core.Models.User","type":"Class"},{"name":"UserStatus","href":"core/EchoHub.Core.Models.UserStatus.html","topicHref":"core/EchoHub.Core.Models.UserStatus.html","topicUid":"EchoHub.Core.Models.UserStatus","type":"Enum"}]},{"name":"EchoHub.Core.Security","href":"core/EchoHub.Core.Security.html","topicHref":"core/EchoHub.Core.Security.html","topicUid":"EchoHub.Core.Security","type":"Namespace","items":[{"name":"RoomCrypto","href":"core/EchoHub.Core.Security.RoomCrypto.html","topicHref":"core/EchoHub.Core.Security.RoomCrypto.html","topicUid":"EchoHub.Core.Security.RoomCrypto","type":"Class"},{"name":"RoomCrypto.DerivedKeys","href":"core/EchoHub.Core.Security.RoomCrypto.DerivedKeys.html","topicHref":"core/EchoHub.Core.Security.RoomCrypto.DerivedKeys.html","topicUid":"EchoHub.Core.Security.RoomCrypto.DerivedKeys","type":"Class"}]},{"name":"EchoHub.Core.Services","href":"core/EchoHub.Core.Services.html","topicHref":"core/EchoHub.Core.Services.html","topicUid":"EchoHub.Core.Services","type":"Namespace","items":[{"name":"AsciiBannerService","href":"core/EchoHub.Core.Services.AsciiBannerService.html","topicHref":"core/EchoHub.Core.Services.AsciiBannerService.html","topicUid":"EchoHub.Core.Services.AsciiBannerService","type":"Class"},{"name":"FileValidationHelper","href":"core/EchoHub.Core.Services.FileValidationHelper.html","topicHref":"core/EchoHub.Core.Services.FileValidationHelper.html","topicUid":"EchoHub.Core.Services.FileValidationHelper","type":"Class"},{"name":"ImageToAsciiService","href":"core/EchoHub.Core.Services.ImageToAsciiService.html","topicHref":"core/EchoHub.Core.Services.ImageToAsciiService.html","topicUid":"EchoHub.Core.Services.ImageToAsciiService","type":"Class"}]}]},{"name":"Articles","includedFrom":"~/api/core-articles/toc.yml","items":[{"name":"Overview","href":"core-articles/index.html","topicHref":"core-articles/index.html"}]}]},{"name":"Server","items":[{"name":"API Reference","includedFrom":"~/_api_meta/server/toc.yml","items":[{"name":"EchoHub.Server.Auth","href":"server/EchoHub.Server.Auth.html","topicHref":"server/EchoHub.Server.Auth.html","topicUid":"EchoHub.Server.Auth","type":"Namespace","items":[{"name":"JwtTokenService","href":"server/EchoHub.Server.Auth.JwtTokenService.html","topicHref":"server/EchoHub.Server.Auth.JwtTokenService.html","topicUid":"EchoHub.Server.Auth.JwtTokenService","type":"Class"}]},{"name":"EchoHub.Server.Config","href":"server/EchoHub.Server.Config.html","topicHref":"server/EchoHub.Server.Config.html","topicUid":"EchoHub.Server.Config","type":"Namespace","items":[{"name":"ServerLogsOptions","href":"server/EchoHub.Server.Config.ServerLogsOptions.html","topicHref":"server/EchoHub.Server.Config.ServerLogsOptions.html","topicUid":"EchoHub.Server.Config.ServerLogsOptions","type":"Class"},{"name":"SpamOptions","href":"server/EchoHub.Server.Config.SpamOptions.html","topicHref":"server/EchoHub.Server.Config.SpamOptions.html","topicUid":"EchoHub.Server.Config.SpamOptions","type":"Class"},{"name":"StatsOptions","href":"server/EchoHub.Server.Config.StatsOptions.html","topicHref":"server/EchoHub.Server.Config.StatsOptions.html","topicUid":"EchoHub.Server.Config.StatsOptions","type":"Class"},{"name":"UploadLimits","href":"server/EchoHub.Server.Config.UploadLimits.html","topicHref":"server/EchoHub.Server.Config.UploadLimits.html","topicUid":"EchoHub.Server.Config.UploadLimits","type":"Class"}]},{"name":"EchoHub.Server.Controllers","href":"server/EchoHub.Server.Controllers.html","topicHref":"server/EchoHub.Server.Controllers.html","topicUid":"EchoHub.Server.Controllers","type":"Namespace","items":[{"name":"AuthController","href":"server/EchoHub.Server.Controllers.AuthController.html","topicHref":"server/EchoHub.Server.Controllers.AuthController.html","topicUid":"EchoHub.Server.Controllers.AuthController","type":"Class"},{"name":"ChannelsController","href":"server/EchoHub.Server.Controllers.ChannelsController.html","topicHref":"server/EchoHub.Server.Controllers.ChannelsController.html","topicUid":"EchoHub.Server.Controllers.ChannelsController","type":"Class"},{"name":"FilesController","href":"server/EchoHub.Server.Controllers.FilesController.html","topicHref":"server/EchoHub.Server.Controllers.FilesController.html","topicUid":"EchoHub.Server.Controllers.FilesController","type":"Class"},{"name":"InvitesController","href":"server/EchoHub.Server.Controllers.InvitesController.html","topicHref":"server/EchoHub.Server.Controllers.InvitesController.html","topicUid":"EchoHub.Server.Controllers.InvitesController","type":"Class"},{"name":"ModerationController","href":"server/EchoHub.Server.Controllers.ModerationController.html","topicHref":"server/EchoHub.Server.Controllers.ModerationController.html","topicUid":"EchoHub.Server.Controllers.ModerationController","type":"Class"},{"name":"ServerController","href":"server/EchoHub.Server.Controllers.ServerController.html","topicHref":"server/EchoHub.Server.Controllers.ServerController.html","topicUid":"EchoHub.Server.Controllers.ServerController","type":"Class"},{"name":"UsersController","href":"server/EchoHub.Server.Controllers.UsersController.html","topicHref":"server/EchoHub.Server.Controllers.UsersController.html","topicUid":"EchoHub.Server.Controllers.UsersController","type":"Class"}]},{"name":"EchoHub.Server.Data","href":"server/EchoHub.Server.Data.html","topicHref":"server/EchoHub.Server.Data.html","topicUid":"EchoHub.Server.Data","type":"Namespace","items":[{"name":"EchoHubDbContext","href":"server/EchoHub.Server.Data.EchoHubDbContext.html","topicHref":"server/EchoHub.Server.Data.EchoHubDbContext.html","topicUid":"EchoHub.Server.Data.EchoHubDbContext","type":"Class"}]},{"name":"EchoHub.Server.Data.Migrations","href":"server/EchoHub.Server.Data.Migrations.html","topicHref":"server/EchoHub.Server.Data.Migrations.html","topicUid":"EchoHub.Server.Data.Migrations","type":"Namespace","items":[{"name":"AddAttachmentFileSize","href":"server/EchoHub.Server.Data.Migrations.AddAttachmentFileSize.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddAttachmentFileSize.html","topicUid":"EchoHub.Server.Data.Migrations.AddAttachmentFileSize","type":"Class"},{"name":"AddChannelEncryptionEnvelope","href":"server/EchoHub.Server.Data.Migrations.AddChannelEncryptionEnvelope.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddChannelEncryptionEnvelope.html","topicUid":"EchoHub.Server.Data.Migrations.AddChannelEncryptionEnvelope","type":"Class"},{"name":"AddChannelIsPublic","href":"server/EchoHub.Server.Data.Migrations.AddChannelIsPublic.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddChannelIsPublic.html","topicUid":"EchoHub.Server.Data.Migrations.AddChannelIsPublic","type":"Class"},{"name":"AddChannelIsSystem","href":"server/EchoHub.Server.Data.Migrations.AddChannelIsSystem.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddChannelIsSystem.html","topicUid":"EchoHub.Server.Data.Migrations.AddChannelIsSystem","type":"Class"},{"name":"AddChannelMembership","href":"server/EchoHub.Server.Data.Migrations.AddChannelMembership.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddChannelMembership.html","topicUid":"EchoHub.Server.Data.Migrations.AddChannelMembership","type":"Class"},{"name":"AddChannelPasswordHash","href":"server/EchoHub.Server.Data.Migrations.AddChannelPasswordHash.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddChannelPasswordHash.html","topicUid":"EchoHub.Server.Data.Migrations.AddChannelPasswordHash","type":"Class"},{"name":"AddEncryptionSupport","href":"server/EchoHub.Server.Data.Migrations.AddEncryptionSupport.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddEncryptionSupport.html","topicUid":"EchoHub.Server.Data.Migrations.AddEncryptionSupport","type":"Class"},{"name":"AddInvitesAndReplies","href":"server/EchoHub.Server.Data.Migrations.AddInvitesAndReplies.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddInvitesAndReplies.html","topicUid":"EchoHub.Server.Data.Migrations.AddInvitesAndReplies","type":"Class"},{"name":"AddMessageAttachments","href":"server/EchoHub.Server.Data.Migrations.AddMessageAttachments.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddMessageAttachments.html","topicUid":"EchoHub.Server.Data.Migrations.AddMessageAttachments","type":"Class"},{"name":"AddMessageEmbed","href":"server/EchoHub.Server.Data.Migrations.AddMessageEmbed.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddMessageEmbed.html","topicUid":"EchoHub.Server.Data.Migrations.AddMessageEmbed","type":"Class"},{"name":"AddModerationRoles","href":"server/EchoHub.Server.Data.Migrations.AddModerationRoles.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddModerationRoles.html","topicUid":"EchoHub.Server.Data.Migrations.AddModerationRoles","type":"Class"},{"name":"AddServerStatsReports","href":"server/EchoHub.Server.Data.Migrations.AddServerStatsReports.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddServerStatsReports.html","topicUid":"EchoHub.Server.Data.Migrations.AddServerStatsReports","type":"Class"},{"name":"InitialCreate","href":"server/EchoHub.Server.Data.Migrations.InitialCreate.html","topicHref":"server/EchoHub.Server.Data.Migrations.InitialCreate.html","topicUid":"EchoHub.Server.Data.Migrations.InitialCreate","type":"Class"}]},{"name":"EchoHub.Server.Hubs","href":"server/EchoHub.Server.Hubs.html","topicHref":"server/EchoHub.Server.Hubs.html","topicUid":"EchoHub.Server.Hubs","type":"Namespace","items":[{"name":"ChatHub","href":"server/EchoHub.Server.Hubs.ChatHub.html","topicHref":"server/EchoHub.Server.Hubs.ChatHub.html","topicUid":"EchoHub.Server.Hubs.ChatHub","type":"Class"}]},{"name":"EchoHub.Server.Services","href":"server/EchoHub.Server.Services.html","topicHref":"server/EchoHub.Server.Services.html","topicUid":"EchoHub.Server.Services","type":"Namespace","items":[{"name":"ChannelService","href":"server/EchoHub.Server.Services.ChannelService.html","topicHref":"server/EchoHub.Server.Services.ChannelService.html","topicUid":"EchoHub.Server.Services.ChannelService","type":"Class"},{"name":"ChatService","href":"server/EchoHub.Server.Services.ChatService.html","topicHref":"server/EchoHub.Server.Services.ChatService.html","topicUid":"EchoHub.Server.Services.ChatService","type":"Class"},{"name":"DirectoryClaimStore","href":"server/EchoHub.Server.Services.DirectoryClaimStore.html","topicHref":"server/EchoHub.Server.Services.DirectoryClaimStore.html","topicUid":"EchoHub.Server.Services.DirectoryClaimStore","type":"Class"},{"name":"FileCleanupService","href":"server/EchoHub.Server.Services.FileCleanupService.html","topicHref":"server/EchoHub.Server.Services.FileCleanupService.html","topicUid":"EchoHub.Server.Services.FileCleanupService","type":"Class"},{"name":"FileStorageService","href":"server/EchoHub.Server.Services.FileStorageService.html","topicHref":"server/EchoHub.Server.Services.FileStorageService.html","topicUid":"EchoHub.Server.Services.FileStorageService","type":"Class"},{"name":"LinkEmbedService","href":"server/EchoHub.Server.Services.LinkEmbedService.html","topicHref":"server/EchoHub.Server.Services.LinkEmbedService.html","topicUid":"EchoHub.Server.Services.LinkEmbedService","type":"Class"},{"name":"MessageEncryptionService","href":"server/EchoHub.Server.Services.MessageEncryptionService.html","topicHref":"server/EchoHub.Server.Services.MessageEncryptionService.html","topicUid":"EchoHub.Server.Services.MessageEncryptionService","type":"Class"},{"name":"MuteExpirationService","href":"server/EchoHub.Server.Services.MuteExpirationService.html","topicHref":"server/EchoHub.Server.Services.MuteExpirationService.html","topicUid":"EchoHub.Server.Services.MuteExpirationService","type":"Class"},{"name":"PresenceTracker","href":"server/EchoHub.Server.Services.PresenceTracker.html","topicHref":"server/EchoHub.Server.Services.PresenceTracker.html","topicUid":"EchoHub.Server.Services.PresenceTracker","type":"Class"},{"name":"RegistrationStatus","href":"server/EchoHub.Server.Services.RegistrationStatus.html","topicHref":"server/EchoHub.Server.Services.RegistrationStatus.html","topicUid":"EchoHub.Server.Services.RegistrationStatus","type":"Class"},{"name":"ServerDirectoryService","href":"server/EchoHub.Server.Services.ServerDirectoryService.html","topicHref":"server/EchoHub.Server.Services.ServerDirectoryService.html","topicUid":"EchoHub.Server.Services.ServerDirectoryService","type":"Class"},{"name":"SignalRBroadcaster","href":"server/EchoHub.Server.Services.SignalRBroadcaster.html","topicHref":"server/EchoHub.Server.Services.SignalRBroadcaster.html","topicUid":"EchoHub.Server.Services.SignalRBroadcaster","type":"Class"},{"name":"SpamGuard","href":"server/EchoHub.Server.Services.SpamGuard.html","topicHref":"server/EchoHub.Server.Services.SpamGuard.html","topicUid":"EchoHub.Server.Services.SpamGuard","type":"Class"},{"name":"SpamVerdict","href":"server/EchoHub.Server.Services.SpamVerdict.html","topicHref":"server/EchoHub.Server.Services.SpamVerdict.html","topicUid":"EchoHub.Server.Services.SpamVerdict","type":"Struct"},{"name":"SpamVerdictKind","href":"server/EchoHub.Server.Services.SpamVerdictKind.html","topicHref":"server/EchoHub.Server.Services.SpamVerdictKind.html","topicUid":"EchoHub.Server.Services.SpamVerdictKind","type":"Enum"},{"name":"UserService","href":"server/EchoHub.Server.Services.UserService.html","topicHref":"server/EchoHub.Server.Services.UserService.html","topicUid":"EchoHub.Server.Services.UserService","type":"Class"}]},{"name":"EchoHub.Server.Services.ServerLogs","href":"server/EchoHub.Server.Services.ServerLogs.html","topicHref":"server/EchoHub.Server.Services.ServerLogs.html","topicUid":"EchoHub.Server.Services.ServerLogs","type":"Namespace","items":[{"name":"LogBacklogEntry","href":"server/EchoHub.Server.Services.ServerLogs.LogBacklogEntry.html","topicHref":"server/EchoHub.Server.Services.ServerLogs.LogBacklogEntry.html","topicUid":"EchoHub.Server.Services.ServerLogs.LogBacklogEntry","type":"Class"},{"name":"ServerLogsService","href":"server/EchoHub.Server.Services.ServerLogs.ServerLogsService.html","topicHref":"server/EchoHub.Server.Services.ServerLogs.ServerLogsService.html","topicUid":"EchoHub.Server.Services.ServerLogs.ServerLogsService","type":"Class"},{"name":"ServerLogsSink","href":"server/EchoHub.Server.Services.ServerLogs.ServerLogsSink.html","topicHref":"server/EchoHub.Server.Services.ServerLogs.ServerLogsSink.html","topicUid":"EchoHub.Server.Services.ServerLogs.ServerLogsSink","type":"Class"},{"name":"ServerLogsStreamService","href":"server/EchoHub.Server.Services.ServerLogs.ServerLogsStreamService.html","topicHref":"server/EchoHub.Server.Services.ServerLogs.ServerLogsStreamService.html","topicUid":"EchoHub.Server.Services.ServerLogs.ServerLogsStreamService","type":"Class"}]},{"name":"EchoHub.Server.Services.Stats","href":"server/EchoHub.Server.Services.Stats.html","topicHref":"server/EchoHub.Server.Services.Stats.html","topicUid":"EchoHub.Server.Services.Stats","type":"Namespace","items":[{"name":"ServerStatsCollector","href":"server/EchoHub.Server.Services.Stats.ServerStatsCollector.html","topicHref":"server/EchoHub.Server.Services.Stats.ServerStatsCollector.html","topicUid":"EchoHub.Server.Services.Stats.ServerStatsCollector","type":"Class"},{"name":"ServerStatsReportService","href":"server/EchoHub.Server.Services.Stats.ServerStatsReportService.html","topicHref":"server/EchoHub.Server.Services.Stats.ServerStatsReportService.html","topicUid":"EchoHub.Server.Services.Stats.ServerStatsReportService","type":"Class"},{"name":"StatsCounters","href":"server/EchoHub.Server.Services.Stats.StatsCounters.html","topicHref":"server/EchoHub.Server.Services.Stats.StatsCounters.html","topicUid":"EchoHub.Server.Services.Stats.StatsCounters","type":"Struct"}]},{"name":"EchoHub.Server.Setup","href":"server/EchoHub.Server.Setup.html","topicHref":"server/EchoHub.Server.Setup.html","topicUid":"EchoHub.Server.Setup","type":"Namespace","items":[{"name":"DataMigrationService","href":"server/EchoHub.Server.Setup.DataMigrationService.html","topicHref":"server/EchoHub.Server.Setup.DataMigrationService.html","topicUid":"EchoHub.Server.Setup.DataMigrationService","type":"Class"},{"name":"DatabaseSetup","href":"server/EchoHub.Server.Setup.DatabaseSetup.html","topicHref":"server/EchoHub.Server.Setup.DatabaseSetup.html","topicUid":"EchoHub.Server.Setup.DatabaseSetup","type":"Class"},{"name":"FirstRunSetup","href":"server/EchoHub.Server.Setup.FirstRunSetup.html","topicHref":"server/EchoHub.Server.Setup.FirstRunSetup.html","topicUid":"EchoHub.Server.Setup.FirstRunSetup","type":"Class"}]}]},{"name":"Articles","includedFrom":"~/api/server-articles/toc.yml","items":[{"name":"Overview","href":"server-articles/index.html","topicHref":"server-articles/index.html"}]}]},{"name":"Server.Irc","items":[{"name":"API Reference","includedFrom":"~/_api_meta/server-irc/toc.yml","items":[{"name":"EchoHub.Server.Irc","href":"server-irc/EchoHub.Server.Irc.html","topicHref":"server-irc/EchoHub.Server.Irc.html","topicUid":"EchoHub.Server.Irc","type":"Namespace","items":[{"name":"IrcBroadcaster","href":"server-irc/EchoHub.Server.Irc.IrcBroadcaster.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcBroadcaster.html","topicUid":"EchoHub.Server.Irc.IrcBroadcaster","type":"Class"},{"name":"IrcClientConnection","href":"server-irc/EchoHub.Server.Irc.IrcClientConnection.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcClientConnection.html","topicUid":"EchoHub.Server.Irc.IrcClientConnection","type":"Class"},{"name":"IrcCommandHandler","href":"server-irc/EchoHub.Server.Irc.IrcCommandHandler.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcCommandHandler.html","topicUid":"EchoHub.Server.Irc.IrcCommandHandler","type":"Class"},{"name":"IrcGatewayService","href":"server-irc/EchoHub.Server.Irc.IrcGatewayService.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcGatewayService.html","topicUid":"EchoHub.Server.Irc.IrcGatewayService","type":"Class"},{"name":"IrcMessage","href":"server-irc/EchoHub.Server.Irc.IrcMessage.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcMessage.html","topicUid":"EchoHub.Server.Irc.IrcMessage","type":"Class"},{"name":"IrcMessageFormatter","href":"server-irc/EchoHub.Server.Irc.IrcMessageFormatter.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcMessageFormatter.html","topicUid":"EchoHub.Server.Irc.IrcMessageFormatter","type":"Class"},{"name":"IrcNumericReply","href":"server-irc/EchoHub.Server.Irc.IrcNumericReply.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcNumericReply.html","topicUid":"EchoHub.Server.Irc.IrcNumericReply","type":"Class"},{"name":"IrcOptions","href":"server-irc/EchoHub.Server.Irc.IrcOptions.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcOptions.html","topicUid":"EchoHub.Server.Irc.IrcOptions","type":"Class"},{"name":"IrcServiceExtensions","href":"server-irc/EchoHub.Server.Irc.IrcServiceExtensions.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcServiceExtensions.html","topicUid":"EchoHub.Server.Irc.IrcServiceExtensions","type":"Class"}]}]}]}]} diff --git a/changelog/index.html b/changelog/index.html index 0d1fe79..e239218 100644 --- a/changelog/index.html +++ b/changelog/index.html @@ -90,6 +90,7 @@

    Release history for EchoHub.

    Releases

      +
    • v0.2.16 - Periodic Server-Stats Report, Upload & Moderation Logging & Quieter Connection Logs
    • v0.2.15 - Invite Codes, Data Export & Deletion, /me, /banner, Replies, Open Images In Browser & IRC Image Links
    • v0.2.14 - Clipboard Image & Multi-File Paste, E2E Room Unlock Fixes, Encrypted Key Cache & IRC Gateway Polish
    • v0.2.13 - Chat Visual Overhaul, Auto-Join All Channels & Persistent Read Positions
    • diff --git a/changelog/toc.html b/changelog/toc.html index c4c3be7..6d82d37 100644 --- a/changelog/toc.html +++ b/changelog/toc.html @@ -15,6 +15,9 @@
    • Overview
    • +
    • + v0.2.16 +
    • v0.2.15
    • diff --git a/changelog/toc.json b/changelog/toc.json index c53ff6d..8867ef0 100644 --- a/changelog/toc.json +++ b/changelog/toc.json @@ -1,2 +1,2 @@ -{"items":[{"name":"Overview","href":"index.html","topicHref":"index.html"},{"name":"v0.2.15","href":"v0.2.15.html","topicHref":"v0.2.15.html"},{"name":"v0.2.14","href":"v0.2.14.html","topicHref":"v0.2.14.html"},{"name":"v0.2.13","href":"v0.2.13.html","topicHref":"v0.2.13.html"},{"name":"v0.2.12","href":"v0.2.12.html","topicHref":"v0.2.12.html"},{"name":"v0.2.11","href":"v0.2.11.html","topicHref":"v0.2.11.html"},{"name":"v0.2.10","href":"v0.2.10.html","topicHref":"v0.2.10.html"},{"name":"v0.2.9","href":"v0.2.9.html","topicHref":"v0.2.9.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"}]} +{"items":[{"name":"Overview","href":"index.html","topicHref":"index.html"},{"name":"v0.2.16","href":"v0.2.16.html","topicHref":"v0.2.16.html"},{"name":"v0.2.15","href":"v0.2.15.html","topicHref":"v0.2.15.html"},{"name":"v0.2.14","href":"v0.2.14.html","topicHref":"v0.2.14.html"},{"name":"v0.2.13","href":"v0.2.13.html","topicHref":"v0.2.13.html"},{"name":"v0.2.12","href":"v0.2.12.html","topicHref":"v0.2.12.html"},{"name":"v0.2.11","href":"v0.2.11.html","topicHref":"v0.2.11.html"},{"name":"v0.2.10","href":"v0.2.10.html","topicHref":"v0.2.10.html"},{"name":"v0.2.9","href":"v0.2.9.html","topicHref":"v0.2.9.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"}]} diff --git a/changelog/v0.2.16.html b/changelog/v0.2.16.html new file mode 100644 index 0000000..b51b28f --- /dev/null +++ b/changelog/v0.2.16.html @@ -0,0 +1,157 @@ + + + + + v0.2.16 | EchoHub Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + +
      +
      +
      +
      +
      Table of Contents
      + +
      +
      + +
      +
      +
      + +
      +
      + + + +
      + +
      +

      v0.2.16

      + +

      A logging and observability pass built on the new server-logs room. Busy servers stop drowning +in connect/disconnect noise, the events operators actually care about — uploads, moderation +actions — now get logged, and a new periodic report summarizes server activity as pretty-printed +JSON that streams into the logs room and is saved to the database for history.

      +

      New Features

      +
        +
      • Periodic server-stats report — every 6 hours (configurable), the server logs an aggregate +activity snapshot as pretty-printed JSON and saves it to the database. Each report covers the +window since the previous one: messages sent, files uploaded (and total bytes), new members, +active members (distinct senders), session connections/disconnections, kicks, bans, total +registered members, users online now, and peak concurrent online. Reports also stream into the +live server-logs room, and old ones are pruned past a configurable retention. New Stats config +section (Stats:Enabled, Stats:IntervalHours = 6, Stats:RetentionDays = 90).
      • +
      • Upload logging — every file, image, and audio upload is now logged with its resource URL +(/api/files/{id}), kind, size, uploader, and channel. In end-to-end encrypted rooms the +filename is client-side ciphertext, so it's logged as [encrypted] — the server still never +sees room content.
      • +
      • Moderation & user-action logging — role changes, kicks, bans, unbans, mutes, unmutes, +moderator message removals, and channel nukes are now logged with the actor, target, and reason. +Bans and channel nukes log at Warning level so they stand out.
      • +
      +

      Improvements

      +
        +
      • Quieter connection logs — user connect, disconnect, join-channel, and leave-channel events +(over both SignalR and IRC) dropped from Information to Debug. On a busy server these fired +constantly and buried everything else; the aggregate counts now live in the periodic stats +report instead. They still show in Development, where the default level is Debug.
      • +
      • Config examples stay in sync — .env.example gained the ServerLogs and Stats sections +(the former had been missing), alongside appsettings.json / appsettings.example.json.
      • +
      +

      Notes for server operators

      +
        +
      • New config section: Stats — Enabled (default true), IntervalHours (default 6), +RetentionDays (default 90, 0 keeps reports forever). See appsettings.example.json and +.env.example. A non-positive interval falls back to 6h; positive values are honored down to a +1-second floor.
      • +
      • One new database migration (AddServerStatsReports) applies automatically on startup.
      • +
      • Connect/disconnect/join/leave now log at Debug — if you relied on those Information lines, lower +Serilog:MinimumLevel:Default (or ServerLogs:MinLevel for the room) to Debug, or read the +periodic stats report for aggregates.
      • +
      + +
      + + + + + +
      + +
      + +
      +
      + +
      + + + + diff --git a/index.json b/index.json index 010cc65..bd5f9dd 100644 --- a/index.json +++ b/index.json @@ -699,6 +699,11 @@ "title": "Enum ServerRole | EchoHub Documentation", "summary": "Enum ServerRole Namespace EchoHub.Core.Models Assembly EchoHub.Core.dll public enum ServerRole Fields Admin = 2 Member = 0 Mod = 1 Owner = 3" }, + "api/core/EchoHub.Core.Models.ServerStatsReport.html": { + "href": "api/core/EchoHub.Core.Models.ServerStatsReport.html", + "title": "Class ServerStatsReport | EchoHub Documentation", + "summary": "Class ServerStatsReport Namespace EchoHub.Core.Models Assembly EchoHub.Core.dll A snapshot of server activity over one reporting window, produced periodically by the stats-report background job. Each report is logged as pretty-printed JSON and persisted for historical trend analysis. The window is \"since the previous report\" (or since startup for the first report of a run). public class ServerStatsReport Inheritance object ServerStatsReport Inherited Members object.GetType() object.MemberwiseClone() object.ToString() object.Equals(object) object.Equals(object, object) object.ReferenceEquals(object, object) object.GetHashCode() Constructors ServerStatsReport() public ServerStatsReport() Properties ActiveMembers Distinct users who sent at least one message during the window. public int ActiveMembers { get; set; } Property Value int Bans Users banned during the window. public int Bans { get; set; } Property Value int BytesUploaded Total bytes across all attachments uploaded during the window. public long BytesUploaded { get; set; } Property Value long Connections Session connects during the window (per-connection, across SignalR + IRC). public int Connections { get; set; } Property Value int Disconnections Session disconnects during the window (\"members left\" sessions). public int Disconnections { get; set; } Property Value int FilesUploaded Attachments (files/images/audio) uploaded during the window. public int FilesUploaded { get; set; } Property Value int GeneratedAt When this report was generated (equals PeriodEnd). public DateTimeOffset GeneratedAt { get; set; } Property Value DateTimeOffset Id public Guid Id { get; set; } Property Value Guid Kicks Users kicked during the window. public int Kicks { get; set; } Property Value int MessagesSent Messages sent during the window. public int MessagesSent { get; set; } Property Value int NewMembers Accounts registered during the window (\"new members joined\"). public int NewMembers { get; set; } Property Value int OnlineNow Distinct users online at window end. public int OnlineNow { get; set; } Property Value int PeakOnline Peak distinct users online observed during the window. public int PeakOnline { get; set; } Property Value int PeriodEnd End of the reporting window. public DateTimeOffset PeriodEnd { get; set; } Property Value DateTimeOffset PeriodStart Start of the reporting window. public DateTimeOffset PeriodStart { get; set; } Property Value DateTimeOffset TotalMembers Total registered (unique) members at window end. public int TotalMembers { get; set; } Property Value int WindowHours Length of the reporting window in hours. public double WindowHours { get; set; } Property Value double" + }, "api/core/EchoHub.Core.Models.User.html": { "href": "api/core/EchoHub.Core.Models.User.html", "title": "Class User | EchoHub Documentation", @@ -712,7 +717,7 @@ "api/core/EchoHub.Core.Models.html": { "href": "api/core/EchoHub.Core.Models.html", "title": "Namespace EchoHub.Core.Models | EchoHub Documentation", - "summary": "Namespace EchoHub.Core.Models Classes Attachment A file attached to a message (image, audio, or any file). A message may carry zero or more attachments alongside its text content (Discord-style). Channel ChannelMembership InviteCode A registration invite code. When the server runs with Server:Registration = \"invite\", new accounts (REST and IRC alike) require a valid, unexpired, not-fully-used code. Message RefreshToken User Enums AttachmentKind The kind of a message attachment. Determines how the client renders it (ASCII preview for images, a play affordance for audio, a download line for files). MessageType ServerRole UserStatus" + "summary": "Namespace EchoHub.Core.Models Classes Attachment A file attached to a message (image, audio, or any file). A message may carry zero or more attachments alongside its text content (Discord-style). Channel ChannelMembership InviteCode A registration invite code. When the server runs with Server:Registration = \"invite\", new accounts (REST and IRC alike) require a valid, unexpired, not-fully-used code. Message RefreshToken ServerStatsReport A snapshot of server activity over one reporting window, produced periodically by the stats-report background job. Each report is logged as pretty-printed JSON and persisted for historical trend analysis. The window is \"since the previous report\" (or since startup for the first report of a run). User Enums AttachmentKind The kind of a message attachment. Determines how the client renders it (ASCII preview for images, a play affordance for audio, a download line for files). MessageType ServerRole UserStatus" }, "api/core/EchoHub.Core.Security.RoomCrypto.DerivedKeys.html": { "href": "api/core/EchoHub.Core.Security.RoomCrypto.DerivedKeys.html", @@ -829,6 +834,11 @@ "title": "Class SpamOptions | EchoHub Documentation", "summary": "Class SpamOptions Namespace EchoHub.Server.Config Assembly EchoHub.Server.dll Anti-spam thresholds, bound from the \"Spam\" config section. Defaults are lenient enough that a fast typist never trips them; Mods and above are always exempt. public sealed class SpamOptions Inheritance object SpamOptions Inherited Members object.GetType() object.ToString() object.Equals(object) object.Equals(object, object) object.ReferenceEquals(object, object) object.GetHashCode() Constructors SpamOptions() public SpamOptions() Properties AutoMuteMinutes Auto-mute duration once a user accumulates ViolationThreshold rejected sends within ViolationWindowMinutes. 0 disables auto-mute (rejections still apply). The mute uses the normal timed-mute machinery, so moderators see it and MuteExpirationService lifts it. public int AutoMuteMinutes { get; set; } Property Value int ChannelCreateWindowMinutes public int ChannelCreateWindowMinutes { get; set; } Property Value int Enabled Master switch for all spam protection. public bool Enabled { get; set; } Property Value bool JoinWindowSeconds public int JoinWindowSeconds { get; set; } Property Value int MaxChannelCreatesPerWindow Max channel creations per ChannelCreateWindowMinutes window. public int MaxChannelCreatesPerWindow { get; set; } Property Value int MaxDuplicateMessages How many identical messages in a row are tolerated; the next one is rejected. (End-to-end encrypted rooms are naturally exempt — identical plaintext produces different ciphertext per message, so repeats never look identical to the server.) public int MaxDuplicateMessages { get; set; } Property Value int MaxJoinsPerWindow Max first-time channel joins per JoinWindowSeconds window. Joins of channels the user already belongs to (reconnect/auto-join) never count, but a brand-new user's first connect joins every public channel at once — keep this above your public channel count. public int MaxJoinsPerWindow { get; set; } Property Value int MaxMessagesPerWindow Max messages a user may send per WindowSeconds window. public int MaxMessagesPerWindow { get; set; } Property Value int ViolationThreshold public int ViolationThreshold { get; set; } Property Value int ViolationWindowMinutes public int ViolationWindowMinutes { get; set; } Property Value int WindowSeconds public int WindowSeconds { get; set; } Property Value int" }, + "api/server/EchoHub.Server.Config.StatsOptions.html": { + "href": "api/server/EchoHub.Server.Config.StatsOptions.html", + "title": "Class StatsOptions | EchoHub Documentation", + "summary": "Class StatsOptions Namespace EchoHub.Server.Config Assembly EchoHub.Server.dll Periodic server-stats report settings, bound from the \"Stats\" config section (env override: Stats__Enabled etc.). When enabled, a background job periodically snapshots server activity, logs it as pretty-printed JSON, and persists it to the database. public sealed class StatsOptions Inheritance object StatsOptions Inherited Members object.GetType() object.ToString() object.Equals(object) object.Equals(object, object) object.ReferenceEquals(object, object) object.GetHashCode() Constructors StatsOptions() public StatsOptions() Properties Enabled Master switch for the periodic stats report job. public bool Enabled { get; set; } Property Value bool IntervalHours How often a report is generated, in hours. Default: every 6 hours. public double IntervalHours { get; set; } Property Value double RetentionDays How long persisted reports are kept before being pruned, in days. Set to 0 to keep reports indefinitely. Default: 90 days. public int RetentionDays { get; set; } Property Value int" + }, "api/server/EchoHub.Server.Config.UploadLimits.html": { "href": "api/server/EchoHub.Server.Config.UploadLimits.html", "title": "Class UploadLimits | EchoHub Documentation", @@ -837,7 +847,7 @@ "api/server/EchoHub.Server.Config.html": { "href": "api/server/EchoHub.Server.Config.html", "title": "Namespace EchoHub.Server.Config | EchoHub Documentation", - "summary": "Namespace EchoHub.Server.Config Classes ServerLogsOptions Live server-log room settings, bound from the \"ServerLogs\" config section (env override: ServerLogs__Enabled etc.). When enabled, a read-only system channel is auto-created and log events are streamed to it live — log lines are never stored as messages in the database; the rolling Serilog log files remain the only persistence. SpamOptions Anti-spam thresholds, bound from the \"Spam\" config section. Defaults are lenient enough that a fast typist never trips them; Mods and above are always exempt. UploadLimits Admin-configurable upload limits, bound from the Uploads configuration section. Sizes are expressed in megabytes in configuration; the *Bytes accessors convert them for enforcement. Every default mirrors HubConstants so an absent or partial Uploads section preserves the historical built-in limits." + "summary": "Namespace EchoHub.Server.Config Classes ServerLogsOptions Live server-log room settings, bound from the \"ServerLogs\" config section (env override: ServerLogs__Enabled etc.). When enabled, a read-only system channel is auto-created and log events are streamed to it live — log lines are never stored as messages in the database; the rolling Serilog log files remain the only persistence. SpamOptions Anti-spam thresholds, bound from the \"Spam\" config section. Defaults are lenient enough that a fast typist never trips them; Mods and above are always exempt. StatsOptions Periodic server-stats report settings, bound from the \"Stats\" config section (env override: Stats__Enabled etc.). When enabled, a background job periodically snapshots server activity, logs it as pretty-printed JSON, and persists it to the database. UploadLimits Admin-configurable upload limits, bound from the Uploads configuration section. Sizes are expressed in megabytes in configuration; the *Bytes accessors convert them for enforcement. Every default mirrors HubConstants so an absent or partial Uploads section preserves the historical built-in limits." }, "api/server/EchoHub.Server.Controllers.AuthController.html": { "href": "api/server/EchoHub.Server.Controllers.AuthController.html", @@ -847,7 +857,7 @@ "api/server/EchoHub.Server.Controllers.ChannelsController.html": { "href": "api/server/EchoHub.Server.Controllers.ChannelsController.html", "title": "Class ChannelsController | EchoHub Documentation", - "summary": "Class ChannelsController Namespace EchoHub.Server.Controllers Assembly EchoHub.Server.dll [ApiController] [Route(\"api/channels\")] [Authorize] [EnableRateLimiting(\"general\")] public class ChannelsController : ControllerBase Inheritance object ControllerBase ChannelsController Inherited Members object.GetType() object.MemberwiseClone() object.ToString() object.Equals(object) object.Equals(object, object) object.ReferenceEquals(object, object) object.GetHashCode() Constructors ChannelsController(IChannelService, EchoHubDbContext, FileStorageService, ImageToAsciiService, IHttpClientFactory, IChatService, IMessageEncryptionService, UploadLimits) public ChannelsController(IChannelService channelService, EchoHubDbContext db, FileStorageService fileStorage, ImageToAsciiService asciiService, IHttpClientFactory httpClientFactory, IChatService chatService, IMessageEncryptionService encryption, UploadLimits uploadLimits) Parameters channelService IChannelService db EchoHubDbContext fileStorage FileStorageService asciiService ImageToAsciiService httpClientFactory IHttpClientFactory chatService IChatService encryption IMessageEncryptionService uploadLimits UploadLimits Methods CreateChannel(CreateChannelRequest) [HttpPost] public Task CreateChannel(CreateChannelRequest request) Parameters request CreateChannelRequest Returns Task DeleteChannel(string) [HttpDelete(\"{channel}\")] public Task DeleteChannel(string channel) Parameters channel string Returns Task GetChannelCrypto(string) Public crypto metadata for a channel: whether it is end-to-end encrypted and the PBKDF2 salt clients need to derive their join credential. Never returns the wrapped room key — that is only handed out after a successful join. [HttpGet(\"{channel}/crypto\")] public Task GetChannelCrypto(string channel) Parameters channel string Returns Task GetChannelMeta(string) Human-facing summary of a channel (message count, unique posters, estimated size, created date, room id). Available for encrypted channels too — these are metadata the server tracks even though it cannot read the messages themselves. [HttpGet(\"{channel}/meta\")] public Task GetChannelMeta(string channel) Parameters channel string Returns Task GetChannels(int, int) [HttpGet] public Task GetChannels(int offset = 0, int limit = 50) Parameters offset int limit int Returns Task RekeyChannel(string, RekeyChannelRequest) Changes an encrypted channel's passphrase by re-wrapping its room key. The caller proves knowledge of the old passphrase via the old auth key; history is never re-encrypted (the room content key does not change). [HttpPost(\"{channel}/rekey\")] public Task RekeyChannel(string channel, RekeyChannelRequest request) Parameters channel string request RekeyChannelRequest Returns Task SendMessageWithAttachments(string, string?) Sends one message carrying optional text (content form field) plus zero or more file attachments (Discord-style). For non-encrypted channels the server sniffs each file's kind and renders ASCII previews for images. For end-to-end encrypted channels the client uploads ciphertext blobs and declares each file's kind (kind) and pre-rendered, room-encrypted preview (preview), aligned by file order — the server never inspects them. [HttpPost(\"{channel}/messages\")] [EnableRateLimiting(\"upload\")] public Task SendMessageWithAttachments(string channel, string? size = null) Parameters channel string size string Returns Task SendUrl(string, SendUrlRequest, string?) [HttpPost(\"{channel}/send-url\")] [EnableRateLimiting(\"upload\")] public Task SendUrl(string channel, SendUrlRequest request, string? size = null) Parameters channel string request SendUrlRequest size string Returns Task UpdateTopic(string, UpdateTopicRequest) [HttpPut(\"{channel}/topic\")] public Task UpdateTopic(string channel, UpdateTopicRequest request) Parameters channel string request UpdateTopicRequest Returns Task" + "summary": "Class ChannelsController Namespace EchoHub.Server.Controllers Assembly EchoHub.Server.dll [ApiController] [Route(\"api/channels\")] [Authorize] [EnableRateLimiting(\"general\")] public class ChannelsController : ControllerBase Inheritance object ControllerBase ChannelsController Inherited Members object.GetType() object.MemberwiseClone() object.ToString() object.Equals(object) object.Equals(object, object) object.ReferenceEquals(object, object) object.GetHashCode() Constructors ChannelsController(IChannelService, EchoHubDbContext, FileStorageService, ImageToAsciiService, IHttpClientFactory, IChatService, IMessageEncryptionService, UploadLimits, ILogger) public ChannelsController(IChannelService channelService, EchoHubDbContext db, FileStorageService fileStorage, ImageToAsciiService asciiService, IHttpClientFactory httpClientFactory, IChatService chatService, IMessageEncryptionService encryption, UploadLimits uploadLimits, ILogger logger) Parameters channelService IChannelService db EchoHubDbContext fileStorage FileStorageService asciiService ImageToAsciiService httpClientFactory IHttpClientFactory chatService IChatService encryption IMessageEncryptionService uploadLimits UploadLimits logger ILogger Methods CreateChannel(CreateChannelRequest) [HttpPost] public Task CreateChannel(CreateChannelRequest request) Parameters request CreateChannelRequest Returns Task DeleteChannel(string) [HttpDelete(\"{channel}\")] public Task DeleteChannel(string channel) Parameters channel string Returns Task GetChannelCrypto(string) Public crypto metadata for a channel: whether it is end-to-end encrypted and the PBKDF2 salt clients need to derive their join credential. Never returns the wrapped room key — that is only handed out after a successful join. [HttpGet(\"{channel}/crypto\")] public Task GetChannelCrypto(string channel) Parameters channel string Returns Task GetChannelMeta(string) Human-facing summary of a channel (message count, unique posters, estimated size, created date, room id). Available for encrypted channels too — these are metadata the server tracks even though it cannot read the messages themselves. [HttpGet(\"{channel}/meta\")] public Task GetChannelMeta(string channel) Parameters channel string Returns Task GetChannels(int, int) [HttpGet] public Task GetChannels(int offset = 0, int limit = 50) Parameters offset int limit int Returns Task RekeyChannel(string, RekeyChannelRequest) Changes an encrypted channel's passphrase by re-wrapping its room key. The caller proves knowledge of the old passphrase via the old auth key; history is never re-encrypted (the room content key does not change). [HttpPost(\"{channel}/rekey\")] public Task RekeyChannel(string channel, RekeyChannelRequest request) Parameters channel string request RekeyChannelRequest Returns Task SendMessageWithAttachments(string, string?) Sends one message carrying optional text (content form field) plus zero or more file attachments (Discord-style). For non-encrypted channels the server sniffs each file's kind and renders ASCII previews for images. For end-to-end encrypted channels the client uploads ciphertext blobs and declares each file's kind (kind) and pre-rendered, room-encrypted preview (preview), aligned by file order — the server never inspects them. [HttpPost(\"{channel}/messages\")] [EnableRateLimiting(\"upload\")] public Task SendMessageWithAttachments(string channel, string? size = null) Parameters channel string size string Returns Task SendUrl(string, SendUrlRequest, string?) [HttpPost(\"{channel}/send-url\")] [EnableRateLimiting(\"upload\")] public Task SendUrl(string channel, SendUrlRequest request, string? size = null) Parameters channel string request SendUrlRequest size string Returns Task UpdateTopic(string, UpdateTopicRequest) [HttpPut(\"{channel}/topic\")] public Task UpdateTopic(string channel, UpdateTopicRequest request) Parameters channel string request UpdateTopicRequest Returns Task" }, "api/server/EchoHub.Server.Controllers.FilesController.html": { "href": "api/server/EchoHub.Server.Controllers.FilesController.html", @@ -862,7 +872,7 @@ "api/server/EchoHub.Server.Controllers.ModerationController.html": { "href": "api/server/EchoHub.Server.Controllers.ModerationController.html", "title": "Class ModerationController | EchoHub Documentation", - "summary": "Class ModerationController Namespace EchoHub.Server.Controllers Assembly EchoHub.Server.dll [ApiController] [Route(\"api/moderation\")] [Authorize] [EnableRateLimiting(\"general\")] public class ModerationController : ControllerBase Inheritance object ControllerBase ModerationController Inherited Members object.GetType() object.MemberwiseClone() object.ToString() object.Equals(object) object.Equals(object, object) object.ReferenceEquals(object, object) object.GetHashCode() Constructors ModerationController(EchoHubDbContext, IChatService, PresenceTracker, FileStorageService, IEnumerable) public ModerationController(EchoHubDbContext db, IChatService chatService, PresenceTracker presenceTracker, FileStorageService fileStorage, IEnumerable broadcasters) Parameters db EchoHubDbContext chatService IChatService presenceTracker PresenceTracker fileStorage FileStorageService broadcasters IEnumerable Methods AssignRole(AssignRoleRequest) [HttpPost(\"role\")] public Task AssignRole(AssignRoleRequest request) Parameters request AssignRoleRequest Returns Task BanUser(string, BanRequest?) [HttpPost(\"ban/{username}\")] public Task BanUser(string username, BanRequest? request = null) Parameters username string request BanRequest Returns Task DeleteMessage(Guid) [HttpDelete(\"messages/{messageId:guid}\")] public Task DeleteMessage(Guid messageId) Parameters messageId Guid Returns Task KickUser(string, KickRequest?) [HttpPost(\"kick/{username}\")] public Task KickUser(string username, KickRequest? request = null) Parameters username string request KickRequest Returns Task MuteUser(string, MuteRequest?) [HttpPost(\"mute/{username}\")] public Task MuteUser(string username, MuteRequest? request = null) Parameters username string request MuteRequest Returns Task NukeChannel(string) [HttpDelete(\"channels/{channel}/nuke\")] public Task NukeChannel(string channel) Parameters channel string Returns Task UnbanUser(string) [HttpPost(\"unban/{username}\")] public Task UnbanUser(string username) Parameters username string Returns Task UnmuteUser(string) [HttpPost(\"unmute/{username}\")] public Task UnmuteUser(string username) Parameters username string Returns Task" + "summary": "Class ModerationController Namespace EchoHub.Server.Controllers Assembly EchoHub.Server.dll [ApiController] [Route(\"api/moderation\")] [Authorize] [EnableRateLimiting(\"general\")] public class ModerationController : ControllerBase Inheritance object ControllerBase ModerationController Inherited Members object.GetType() object.MemberwiseClone() object.ToString() object.Equals(object) object.Equals(object, object) object.ReferenceEquals(object, object) object.GetHashCode() Constructors ModerationController(EchoHubDbContext, IChatService, PresenceTracker, FileStorageService, IEnumerable, ServerStatsCollector, ILogger) public ModerationController(EchoHubDbContext db, IChatService chatService, PresenceTracker presenceTracker, FileStorageService fileStorage, IEnumerable broadcasters, ServerStatsCollector statsCollector, ILogger logger) Parameters db EchoHubDbContext chatService IChatService presenceTracker PresenceTracker fileStorage FileStorageService broadcasters IEnumerable statsCollector ServerStatsCollector logger ILogger Methods AssignRole(AssignRoleRequest) [HttpPost(\"role\")] public Task AssignRole(AssignRoleRequest request) Parameters request AssignRoleRequest Returns Task BanUser(string, BanRequest?) [HttpPost(\"ban/{username}\")] public Task BanUser(string username, BanRequest? request = null) Parameters username string request BanRequest Returns Task DeleteMessage(Guid) [HttpDelete(\"messages/{messageId:guid}\")] public Task DeleteMessage(Guid messageId) Parameters messageId Guid Returns Task KickUser(string, KickRequest?) [HttpPost(\"kick/{username}\")] public Task KickUser(string username, KickRequest? request = null) Parameters username string request KickRequest Returns Task MuteUser(string, MuteRequest?) [HttpPost(\"mute/{username}\")] public Task MuteUser(string username, MuteRequest? request = null) Parameters username string request MuteRequest Returns Task NukeChannel(string) [HttpDelete(\"channels/{channel}/nuke\")] public Task NukeChannel(string channel) Parameters channel string Returns Task UnbanUser(string) [HttpPost(\"unban/{username}\")] public Task UnbanUser(string username) Parameters username string Returns Task UnmuteUser(string) [HttpPost(\"unmute/{username}\")] public Task UnmuteUser(string username) Parameters username string Returns Task" }, "api/server/EchoHub.Server.Controllers.ServerController.html": { "href": "api/server/EchoHub.Server.Controllers.ServerController.html", @@ -882,7 +892,7 @@ "api/server/EchoHub.Server.Data.EchoHubDbContext.html": { "href": "api/server/EchoHub.Server.Data.EchoHubDbContext.html", "title": "Class EchoHubDbContext | EchoHub Documentation", - "summary": "Class EchoHubDbContext Namespace EchoHub.Server.Data Assembly EchoHub.Server.dll public class EchoHubDbContext : DbContext, IDisposable, IAsyncDisposable Inheritance object DbContext EchoHubDbContext Implements IDisposable IAsyncDisposable Inherited Members object.GetType() object.MemberwiseClone() object.ToString() object.Equals(object) object.Equals(object, object) object.ReferenceEquals(object, object) object.GetHashCode() Constructors EchoHubDbContext(DbContextOptions) public EchoHubDbContext(DbContextOptions options) Parameters options DbContextOptions Properties Attachments public DbSet Attachments { get; } Property Value DbSet ChannelMemberships public DbSet ChannelMemberships { get; } Property Value DbSet Channels public DbSet Channels { get; } Property Value DbSet InviteCodes public DbSet InviteCodes { get; } Property Value DbSet Messages public DbSet Messages { get; } Property Value DbSet RefreshTokens public DbSet RefreshTokens { get; } Property Value DbSet Users public DbSet Users { get; } Property Value DbSet Methods OnConfiguring(DbContextOptionsBuilder) protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) Parameters optionsBuilder DbContextOptionsBuilder OnModelCreating(ModelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder) Parameters modelBuilder ModelBuilder" + "summary": "Class EchoHubDbContext Namespace EchoHub.Server.Data Assembly EchoHub.Server.dll public class EchoHubDbContext : DbContext, IDisposable, IAsyncDisposable Inheritance object DbContext EchoHubDbContext Implements IDisposable IAsyncDisposable Inherited Members object.GetType() object.MemberwiseClone() object.ToString() object.Equals(object) object.Equals(object, object) object.ReferenceEquals(object, object) object.GetHashCode() Constructors EchoHubDbContext(DbContextOptions) public EchoHubDbContext(DbContextOptions options) Parameters options DbContextOptions Properties Attachments public DbSet Attachments { get; } Property Value DbSet ChannelMemberships public DbSet ChannelMemberships { get; } Property Value DbSet Channels public DbSet Channels { get; } Property Value DbSet InviteCodes public DbSet InviteCodes { get; } Property Value DbSet Messages public DbSet Messages { get; } Property Value DbSet RefreshTokens public DbSet RefreshTokens { get; } Property Value DbSet ServerStatsReports public DbSet ServerStatsReports { get; } Property Value DbSet Users public DbSet Users { get; } Property Value DbSet Methods OnConfiguring(DbContextOptionsBuilder) protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) Parameters optionsBuilder DbContextOptionsBuilder OnModelCreating(ModelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder) Parameters modelBuilder ModelBuilder" }, "api/server/EchoHub.Server.Data.Migrations.AddAttachmentFileSize.html": { "href": "api/server/EchoHub.Server.Data.Migrations.AddAttachmentFileSize.html", @@ -939,6 +949,11 @@ "title": "Class AddModerationRoles | EchoHub Documentation", "summary": "Class AddModerationRoles Namespace EchoHub.Server.Data.Migrations Assembly EchoHub.Server.dll [DbContext(typeof(EchoHubDbContext))] [Migration(\"20260219162414_AddModerationRoles\")] public class AddModerationRoles : Migration Inheritance object Migration AddModerationRoles Inherited Members object.GetType() object.MemberwiseClone() object.ToString() object.Equals(object) object.Equals(object, object) object.ReferenceEquals(object, object) object.GetHashCode() Constructors AddModerationRoles() public AddModerationRoles() Methods BuildTargetModel(ModelBuilder) protected override void BuildTargetModel(ModelBuilder modelBuilder) Parameters modelBuilder ModelBuilder Down(MigrationBuilder) protected override void Down(MigrationBuilder migrationBuilder) Parameters migrationBuilder MigrationBuilder Up(MigrationBuilder) protected override void Up(MigrationBuilder migrationBuilder) Parameters migrationBuilder MigrationBuilder" }, + "api/server/EchoHub.Server.Data.Migrations.AddServerStatsReports.html": { + "href": "api/server/EchoHub.Server.Data.Migrations.AddServerStatsReports.html", + "title": "Class AddServerStatsReports | EchoHub Documentation", + "summary": "Class AddServerStatsReports Namespace EchoHub.Server.Data.Migrations Assembly EchoHub.Server.dll [DbContext(typeof(EchoHubDbContext))] [Migration(\"20260717200332_AddServerStatsReports\")] public class AddServerStatsReports : Migration Inheritance object Migration AddServerStatsReports Inherited Members object.GetType() object.MemberwiseClone() object.ToString() object.Equals(object) object.Equals(object, object) object.ReferenceEquals(object, object) object.GetHashCode() Constructors AddServerStatsReports() public AddServerStatsReports() Methods BuildTargetModel(ModelBuilder) protected override void BuildTargetModel(ModelBuilder modelBuilder) Parameters modelBuilder ModelBuilder Down(MigrationBuilder) protected override void Down(MigrationBuilder migrationBuilder) Parameters migrationBuilder MigrationBuilder Up(MigrationBuilder) protected override void Up(MigrationBuilder migrationBuilder) Parameters migrationBuilder MigrationBuilder" + }, "api/server/EchoHub.Server.Data.Migrations.InitialCreate.html": { "href": "api/server/EchoHub.Server.Data.Migrations.InitialCreate.html", "title": "Class InitialCreate | EchoHub Documentation", @@ -947,7 +962,7 @@ "api/server/EchoHub.Server.Data.Migrations.html": { "href": "api/server/EchoHub.Server.Data.Migrations.html", "title": "Namespace EchoHub.Server.Data.Migrations | EchoHub Documentation", - "summary": "Namespace EchoHub.Server.Data.Migrations Classes AddAttachmentFileSize AddChannelEncryptionEnvelope AddChannelIsPublic AddChannelIsSystem AddChannelMembership AddChannelPasswordHash AddEncryptionSupport AddInvitesAndReplies AddMessageAttachments AddMessageEmbed AddModerationRoles InitialCreate" + "summary": "Namespace EchoHub.Server.Data.Migrations Classes AddAttachmentFileSize AddChannelEncryptionEnvelope AddChannelIsPublic AddChannelIsSystem AddChannelMembership AddChannelPasswordHash AddEncryptionSupport AddInvitesAndReplies AddMessageAttachments AddMessageEmbed AddModerationRoles AddServerStatsReports InitialCreate" }, "api/server/EchoHub.Server.Data.html": { "href": "api/server/EchoHub.Server.Data.html", @@ -972,7 +987,7 @@ "api/server/EchoHub.Server.Services.ChatService.html": { "href": "api/server/EchoHub.Server.Services.ChatService.html", "title": "Class ChatService | EchoHub Documentation", - "summary": "Class ChatService Namespace EchoHub.Server.Services Assembly EchoHub.Server.dll public class ChatService : IChatService Inheritance object ChatService Implements IChatService Inherited Members object.GetType() object.MemberwiseClone() object.ToString() object.Equals(object) object.Equals(object, object) object.ReferenceEquals(object, object) object.GetHashCode() Constructors ChatService(IServiceScopeFactory, PresenceTracker, IEnumerable, LinkEmbedService, IMessageEncryptionService, IChannelService, FileStorageService, SpamGuard, ServerLogsService, ILogger) public ChatService(IServiceScopeFactory scopeFactory, PresenceTracker presenceTracker, IEnumerable broadcasters, LinkEmbedService embedService, IMessageEncryptionService encryption, IChannelService channelService, FileStorageService fileStorage, SpamGuard spamGuard, ServerLogsService serverLogs, ILogger logger) Parameters scopeFactory IServiceScopeFactory presenceTracker PresenceTracker broadcasters IEnumerable embedService LinkEmbedService encryption IMessageEncryptionService channelService IChannelService fileStorage FileStorageService spamGuard SpamGuard serverLogs ServerLogsService logger ILogger Methods BroadcastChannelDeletedAsync(string) public Task BroadcastChannelDeletedAsync(string channelName) Parameters channelName string Returns Task BroadcastChannelUpdatedAsync(ChannelDto, string?) public Task BroadcastChannelUpdatedAsync(ChannelDto channel, string? channelName = null) Parameters channel ChannelDto channelName string Returns Task BroadcastMessageAsync(string, MessageDto) public Task BroadcastMessageAsync(string channelName, MessageDto message) Parameters channelName string message MessageDto Returns Task GetChannelHistoryAsync(string, int, int) public Task> GetChannelHistoryAsync(string channelName, int count, int offset = 0) Parameters channelName string count int offset int Returns Task> GetChannelsForUserAsync(string) public Task> GetChannelsForUserAsync(string username) Parameters username string Returns Task> GetOnlineUsersAsync(string) public Task> GetOnlineUsersAsync(string channelName) Parameters channelName string Returns Task> JoinChannelAsync(string, Guid, string, string, string?) public Task<(List History, string? Error, bool PasswordRequired)> JoinChannelAsync(string connectionId, Guid userId, string username, string channelName, string? password = null) Parameters connectionId string userId Guid username string channelName string password string Returns Task<(List History, string Error, bool PasswordRequired)> LeaveChannelAsync(string, string, string) public Task LeaveChannelAsync(string connectionId, string username, string channelName) Parameters connectionId string username string channelName string Returns Task SendMessageAsync(Guid, string, string, string, string?, Guid?) public Task SendMessageAsync(Guid userId, string username, string channelName, string content, string? originConnectionId = null, Guid? replyToMessageId = null) Parameters userId Guid username string channelName string content string originConnectionId string replyToMessageId Guid? Returns Task UpdateStatusAsync(Guid, string, UserStatus, string?) public Task UpdateStatusAsync(Guid userId, string username, UserStatus status, string? statusMessage) Parameters userId Guid username string status UserStatus statusMessage string Returns Task UserConnectedAsync(string, Guid, string) public Task UserConnectedAsync(string connectionId, Guid userId, string username) Parameters connectionId string userId Guid username string Returns Task UserDisconnectedAsync(string) public Task UserDisconnectedAsync(string connectionId) Parameters connectionId string Returns Task" + "summary": "Class ChatService Namespace EchoHub.Server.Services Assembly EchoHub.Server.dll public class ChatService : IChatService Inheritance object ChatService Implements IChatService Inherited Members object.GetType() object.MemberwiseClone() object.ToString() object.Equals(object) object.Equals(object, object) object.ReferenceEquals(object, object) object.GetHashCode() Constructors ChatService(IServiceScopeFactory, PresenceTracker, IEnumerable, LinkEmbedService, IMessageEncryptionService, IChannelService, FileStorageService, SpamGuard, ServerLogsService, ServerStatsCollector, ILogger) public ChatService(IServiceScopeFactory scopeFactory, PresenceTracker presenceTracker, IEnumerable broadcasters, LinkEmbedService embedService, IMessageEncryptionService encryption, IChannelService channelService, FileStorageService fileStorage, SpamGuard spamGuard, ServerLogsService serverLogs, ServerStatsCollector statsCollector, ILogger logger) Parameters scopeFactory IServiceScopeFactory presenceTracker PresenceTracker broadcasters IEnumerable embedService LinkEmbedService encryption IMessageEncryptionService channelService IChannelService fileStorage FileStorageService spamGuard SpamGuard serverLogs ServerLogsService statsCollector ServerStatsCollector logger ILogger Methods BroadcastChannelDeletedAsync(string) public Task BroadcastChannelDeletedAsync(string channelName) Parameters channelName string Returns Task BroadcastChannelUpdatedAsync(ChannelDto, string?) public Task BroadcastChannelUpdatedAsync(ChannelDto channel, string? channelName = null) Parameters channel ChannelDto channelName string Returns Task BroadcastMessageAsync(string, MessageDto) public Task BroadcastMessageAsync(string channelName, MessageDto message) Parameters channelName string message MessageDto Returns Task GetChannelHistoryAsync(string, int, int) public Task> GetChannelHistoryAsync(string channelName, int count, int offset = 0) Parameters channelName string count int offset int Returns Task> GetChannelsForUserAsync(string) public Task> GetChannelsForUserAsync(string username) Parameters username string Returns Task> GetOnlineUsersAsync(string) public Task> GetOnlineUsersAsync(string channelName) Parameters channelName string Returns Task> JoinChannelAsync(string, Guid, string, string, string?) public Task<(List History, string? Error, bool PasswordRequired)> JoinChannelAsync(string connectionId, Guid userId, string username, string channelName, string? password = null) Parameters connectionId string userId Guid username string channelName string password string Returns Task<(List History, string Error, bool PasswordRequired)> LeaveChannelAsync(string, string, string) public Task LeaveChannelAsync(string connectionId, string username, string channelName) Parameters connectionId string username string channelName string Returns Task SendMessageAsync(Guid, string, string, string, string?, Guid?) public Task SendMessageAsync(Guid userId, string username, string channelName, string content, string? originConnectionId = null, Guid? replyToMessageId = null) Parameters userId Guid username string channelName string content string originConnectionId string replyToMessageId Guid? Returns Task UpdateStatusAsync(Guid, string, UserStatus, string?) public Task UpdateStatusAsync(Guid userId, string username, UserStatus status, string? statusMessage) Parameters userId Guid username string status UserStatus statusMessage string Returns Task UserConnectedAsync(string, Guid, string) public Task UserConnectedAsync(string connectionId, Guid userId, string username) Parameters connectionId string userId Guid username string Returns Task UserDisconnectedAsync(string) public Task UserDisconnectedAsync(string connectionId) Parameters connectionId string Returns Task" }, "api/server/EchoHub.Server.Services.DirectoryClaimStore.html": { "href": "api/server/EchoHub.Server.Services.DirectoryClaimStore.html", @@ -1064,6 +1079,26 @@ "title": "Enum SpamVerdictKind | EchoHub Documentation", "summary": "Enum SpamVerdictKind Namespace EchoHub.Server.Services Assembly EchoHub.Server.dll public enum SpamVerdictKind Fields Allowed = 0 AutoMute = 2 The user crossed the violation threshold — the caller should apply a timed mute. Rejected = 1" }, + "api/server/EchoHub.Server.Services.Stats.ServerStatsCollector.html": { + "href": "api/server/EchoHub.Server.Services.Stats.ServerStatsCollector.html", + "title": "Class ServerStatsCollector | EchoHub Documentation", + "summary": "Class ServerStatsCollector Namespace EchoHub.Server.Services.Stats Assembly EchoHub.Server.dll Thread-safe, in-memory accumulator for server-activity counters that have no natural database timestamp to query after the fact — session connects/disconnects, moderation actions, and peak concurrency. The periodic stats-report job snapshots and resets these once per reporting window. Registered as a singleton; every increment is lock-free so it is safe to call from hot paths (connect/disconnect). public sealed class ServerStatsCollector Inheritance object ServerStatsCollector Inherited Members object.GetType() object.ToString() object.Equals(object) object.Equals(object, object) object.ReferenceEquals(object, object) object.GetHashCode() Constructors ServerStatsCollector() public ServerStatsCollector() Methods RecordBan() Record a ban action. public void RecordBan() RecordConnection(int) Record a session coming online, updating the running peak. public void RecordConnection(int onlineNow) Parameters onlineNow int RecordDisconnection(int) Record a session going offline, updating the running peak. public void RecordDisconnection(int onlineNow) Parameters onlineNow int RecordKick() Record a kick action. public void RecordKick() RecordOnline(int) Update the running maximum of concurrent online users (lock-free). public void RecordOnline(int onlineNow) Parameters onlineNow int SnapshotAndReset(int) Atomically read all counters and reset them for the next reporting window. The peak is reset to onlineNow so the next window's peak starts from the current concurrency rather than zero. public StatsCounters SnapshotAndReset(int onlineNow) Parameters onlineNow int Returns StatsCounters" + }, + "api/server/EchoHub.Server.Services.Stats.ServerStatsReportService.html": { + "href": "api/server/EchoHub.Server.Services.Stats.ServerStatsReportService.html", + "title": "Class ServerStatsReportService | EchoHub Documentation", + "summary": "Class ServerStatsReportService Namespace EchoHub.Server.Services.Stats Assembly EchoHub.Server.dll Background job that periodically snapshots server activity over a window, logs it as pretty-printed JSON (which also surfaces in the live server-logs room), and persists it to the database for historical trends. Interval and retention are configurable via the \"Stats\" section; the default cadence is every 6 hours. public sealed class ServerStatsReportService : BackgroundService, IDisposable Inheritance object BackgroundService ServerStatsReportService Implements IDisposable Inherited Members object.GetType() object.ToString() object.Equals(object) object.Equals(object, object) object.ReferenceEquals(object, object) object.GetHashCode() Constructors ServerStatsReportService(IServiceScopeFactory, PresenceTracker, ServerStatsCollector, StatsOptions, ILogger) public ServerStatsReportService(IServiceScopeFactory scopeFactory, PresenceTracker presence, ServerStatsCollector collector, StatsOptions options, ILogger logger) Parameters scopeFactory IServiceScopeFactory presence PresenceTracker collector ServerStatsCollector options StatsOptions logger ILogger Methods ExecuteAsync(CancellationToken) protected override Task ExecuteAsync(CancellationToken stoppingToken) Parameters stoppingToken CancellationToken Returns Task" + }, + "api/server/EchoHub.Server.Services.Stats.StatsCounters.html": { + "href": "api/server/EchoHub.Server.Services.Stats.StatsCounters.html", + "title": "Struct StatsCounters | EchoHub Documentation", + "summary": "Struct StatsCounters Namespace EchoHub.Server.Services.Stats Assembly EchoHub.Server.dll Immutable snapshot of the counters held by ServerStatsCollector. public readonly struct StatsCounters : IEquatable Implements IEquatable Inherited Members object.GetType() object.Equals(object, object) object.ReferenceEquals(object, object) Constructors StatsCounters(long, long, long, long, int) Immutable snapshot of the counters held by ServerStatsCollector. public StatsCounters(long Connections, long Disconnections, long Kicks, long Bans, int PeakOnline) Parameters Connections long Disconnections long Kicks long Bans long PeakOnline int Properties Bans public long Bans { get; init; } Property Value long Connections public long Connections { get; init; } Property Value long Disconnections public long Disconnections { get; init; } Property Value long Kicks public long Kicks { get; init; } Property Value long PeakOnline public int PeakOnline { get; init; } Property Value int Methods Deconstruct(out long, out long, out long, out long, out int) public void Deconstruct(out long Connections, out long Disconnections, out long Kicks, out long Bans, out int PeakOnline) Parameters Connections long Disconnections long Kicks long Bans long PeakOnline int Equals(StatsCounters) public bool Equals(StatsCounters other) Parameters other StatsCounters Returns bool Equals(object) public override bool Equals(object obj) Parameters obj object Returns bool GetHashCode() public override int GetHashCode() Returns int ToString() public override string ToString() Returns string Operators operator ==(StatsCounters, StatsCounters) public static bool operator ==(StatsCounters left, StatsCounters right) Parameters left StatsCounters right StatsCounters Returns bool operator !=(StatsCounters, StatsCounters) public static bool operator !=(StatsCounters left, StatsCounters right) Parameters left StatsCounters right StatsCounters Returns bool" + }, + "api/server/EchoHub.Server.Services.Stats.html": { + "href": "api/server/EchoHub.Server.Services.Stats.html", + "title": "Namespace EchoHub.Server.Services.Stats | EchoHub Documentation", + "summary": "Namespace EchoHub.Server.Services.Stats Classes ServerStatsCollector Thread-safe, in-memory accumulator for server-activity counters that have no natural database timestamp to query after the fact — session connects/disconnects, moderation actions, and peak concurrency. The periodic stats-report job snapshots and resets these once per reporting window. Registered as a singleton; every increment is lock-free so it is safe to call from hot paths (connect/disconnect). ServerStatsReportService Background job that periodically snapshots server activity over a window, logs it as pretty-printed JSON (which also surfaces in the live server-logs room), and persists it to the database for historical trends. Interval and retention are configurable via the \"Stats\" section; the default cadence is every 6 hours. Structs StatsCounters Immutable snapshot of the counters held by ServerStatsCollector." + }, "api/server/EchoHub.Server.Services.UserService.html": { "href": "api/server/EchoHub.Server.Services.UserService.html", "title": "Class UserService | EchoHub Documentation", @@ -1152,7 +1187,7 @@ "changelog/index.html": { "href": "changelog/index.html", "title": "Changelog | EchoHub Documentation", - "summary": "Changelog Release history for EchoHub. Releases v0.2.15 - Invite Codes, Data Export & Deletion, /me, /banner, Replies, Open Images In Browser & IRC Image Links v0.2.14 - Clipboard Image & Multi-File Paste, E2E Room Unlock Fixes, Encrypted Key Cache & IRC Gateway Polish v0.2.13 - Chat Visual Overhaul, Auto-Join All Channels & Persistent Read Positions v0.2.12 - End-to-End Encrypted Channels, IRC Channel Keys, Image Save & Ctrl+W Crash Fix v0.2.11 - EchoHubSpace Auth, Live Directory Updates & Server Browser Metadata v0.2.10 - Command Palette, Infinite History Scroll & Auto-Updater Fixes v0.2.9 - Install Script & Chocolatey Fixes v0.2.8 - Docker Support, IRC Account Creation & BOM Fix v0.2.7 - User List Fix & Terminal.Gui NuGet Migration v0.2.6 - Major Refactoring & Code Organization v0.2.5 - Session Persistence, Auto-Updates, Audio & Transparent Theme v0.2.4 - E2E Message Encryption v0.2.3 - Moderation, Embeds & UI Overhaul v0.2.2 - Startup & Shutdown Fixes v0.2.1 - Shutdown & CI Fixes v0.2.0 - IRC Gateway v0.1.1 - Directory Connection Self-Healing v0.1.0 - Initial Release" + "summary": "Changelog Release history for EchoHub. Releases v0.2.16 - Periodic Server-Stats Report, Upload & Moderation Logging & Quieter Connection Logs v0.2.15 - Invite Codes, Data Export & Deletion, /me, /banner, Replies, Open Images In Browser & IRC Image Links v0.2.14 - Clipboard Image & Multi-File Paste, E2E Room Unlock Fixes, Encrypted Key Cache & IRC Gateway Polish v0.2.13 - Chat Visual Overhaul, Auto-Join All Channels & Persistent Read Positions v0.2.12 - End-to-End Encrypted Channels, IRC Channel Keys, Image Save & Ctrl+W Crash Fix v0.2.11 - EchoHubSpace Auth, Live Directory Updates & Server Browser Metadata v0.2.10 - Command Palette, Infinite History Scroll & Auto-Updater Fixes v0.2.9 - Install Script & Chocolatey Fixes v0.2.8 - Docker Support, IRC Account Creation & BOM Fix v0.2.7 - User List Fix & Terminal.Gui NuGet Migration v0.2.6 - Major Refactoring & Code Organization v0.2.5 - Session Persistence, Auto-Updates, Audio & Transparent Theme v0.2.4 - E2E Message Encryption v0.2.3 - Moderation, Embeds & UI Overhaul v0.2.2 - Startup & Shutdown Fixes v0.2.1 - Shutdown & CI Fixes v0.2.0 - IRC Gateway v0.1.1 - Directory Connection Self-Healing v0.1.0 - Initial Release" }, "changelog/v0.1.0.html": { "href": "changelog/v0.1.0.html", @@ -1204,6 +1239,11 @@ "title": "v0.2.15 | EchoHub Documentation", "summary": "v0.2.15 A big one. Server owners can gate registration behind invite codes, users can export or delete everything the server holds about them, and chat gets three classics — /me actions that interop natively with IRC, /banner ASCII text, and message replies with quote rendering and jump-to-original. Images become properly shareable: every image gets an [open] action that views it in your browser (or, in end-to-end encrypted rooms, decrypts and opens it locally). The IRC gateway stops painting ANSI art nobody asked for and posts plain image links any IRC client can open or auto-preview. And a long-standing dual-session annoyance is fixed: messages you send from the TUI now reach your own connected IRC client instantly. New Features Invite-gated registration — set Server:Registration to \"invite\" (or \"closed\") in appsettings.json and new accounts require a valid invite code; the default \"open\" keeps today's behavior. Admins mint codes with /invite [uses] [hours] (single-use, never-expiring by default), list them with /invite list, and revoke with /invite revoke . Codes are unguessable (K7QM-3XPF style), stored only in your server's own database, and consumed atomically so a code's last use can't be taken twice. The IRC gateway respects the gate too: unknown nicknames connecting to an invite-only server get a clear error instead of a silent auto-registered account. The very first account (server owner bootstrap) is always allowed. Data export — /export downloads everything the server stores about you (profile, your messages, attachment metadata) as JSON into your download folder. Content from end-to-end encrypted rooms appears as ciphertext, because the server never had the plaintext — \"you own the data\", demonstrably. Account deletion — /deleteaccount permanently removes your account after a typed confirmation and password re-check: profile, sessions, and every file you uploaded are deleted. Your messages remain (deleting them would gut other people's conversations) but are re-attributed to a reserved deleted-user name. The last remaining Owner can't self-delete. /me actions — /me waves renders as * nick waves. On the wire it's a real CTCP ACTION, so irssi/WeeChat users see a native action line, and their /me renders properly in the TUI. Works in encrypted rooms (the marker encrypts with the text). /banner — renders short text (up to 20 characters) as a 5-row block-letter banner. Rendered locally with a built-in font — no network, no dependencies — and sent as plain message content, so it works over IRC and in encrypted rooms. Message replies — right-click a message (or F6-select) and pick Reply: the input shows a \"Replying to\" strip (Esc cancels), and the sent message renders with a dim ┌ nick: snippet quote line. Activating the quote line jumps to the original message. Being replied to lights up the channel like an @mention. IRC clients see the familiar > nick: snippet | text convention. In encrypted rooms the quoted snippet is decrypted client-side with the room key — the server still never reads room content. [open] images without saving them — every image attachment now shows [open] [↓ save original] beneath its preview. Open views the image in your default browser straight from the server; in end-to-end encrypted rooms (where a browser would only see ciphertext) the client downloads, decrypts with the room key, and opens the image in your OS viewer from a temp file instead. Both actions are individually clickable, Enter on the line opens, and the right-click menu carries both. Attachment links work in a browser — GET /api/files/{id} is now a capability URL: the unguessable GUID in the link is the access token (Discord-CDN style), so attachment links can be opened directly in a browser or shared to IRC without a login token. Images and audio are served inline so the browser displays them instead of forcing a download. Blobs from encrypted rooms remain ciphertext, so their links reveal nothing. IRC gets image links instead of terminal art — the gateway no longer floods IRC clients with truecolor-ANSI ASCII art for images. Each attachment is now a single line — [Image: photo.png] https://your-server/api/files/… — the convention every IRC client understands, and ones like TheLounge or IRCCloud auto-preview. Set the new Irc:PublicBaseUrl option (e.g. \"https://chat.example.com\") so those links come out absolute; unset, they fall back to relative paths as before. Spam protection — per-user message flood and duplicate-message limits, join and channel-creation throttles, and automatic escalation: enough rejected sends in a few minutes earns a timed auto-mute through the normal mute system (moderators see it, and it expires on its own). One guard covers every ingress — TUI and IRC clients hit the same limits. Mods and above are exempt, everything is configurable under the new Spam section (Spam:Enabled master switch, lenient defaults a fast typist won't trip), and the guard only ever sees stored content — encrypted-room messages stay ciphertext. Improvements Strict /status — /status garbage is now an error instead of silently becoming your status message (and resetting you to Online). Status messages moved to /status msg , which preserves your current status; /status msg with no text clears it. The server also rejects out-of-range status values sent by misbehaving clients. Registration dialog — gained Invite Code support, and the Display Name field you could already type into is now actually sent with registration. Bug Fixes Messages sent from the TUI now reach your own IRC session. With the same account online via both the TUI and an IRC client, messages sent from the TUI never appeared in the IRC client until it reconnected (which replayed history). The gateway suppressed the sender's echo by nickname, which swallowed the message for every IRC connection on that account — it now excludes only the exact connection a message originated from, so all your other sessions (a second IRC client included) receive it immediately. Channel deleted event — when a channel is deleted, all connected clients are now immediately notified via the new ChannelDeleted SignalR event. The channel is removed from the channel list. Previously only the deleting client was able to delete the channel. Other clients would see the channel linger until the next manual refresh. Deleted accounts don't break history — channel history now left-joins users, so messages from deleted accounts render (as deleted-user) instead of silently disappearing. Notes for server operators New config key: Server:Registration — \"open\" (default), \"invite\", or \"closed\". New config section: Spam — flood/duplicate/join/create thresholds and auto-mute duration; see appsettings.example.json. On by default with lenient limits; Spam:Enabled: false turns it all off. Note Spam:MaxJoinsPerWindow counts only first-time channel joins — keep it above your public channel count so a new member's first connect isn't throttled. New REST endpoints: POST/GET/DELETE /api/invites (Admin+), GET /api/users/me/export, DELETE /api/users/me. One new database migration (AddInvitesAndReplies) applies automatically on startup." }, + "changelog/v0.2.16.html": { + "href": "changelog/v0.2.16.html", + "title": "v0.2.16 | EchoHub Documentation", + "summary": "v0.2.16 A logging and observability pass built on the new server-logs room. Busy servers stop drowning in connect/disconnect noise, the events operators actually care about — uploads, moderation actions — now get logged, and a new periodic report summarizes server activity as pretty-printed JSON that streams into the logs room and is saved to the database for history. New Features Periodic server-stats report — every 6 hours (configurable), the server logs an aggregate activity snapshot as pretty-printed JSON and saves it to the database. Each report covers the window since the previous one: messages sent, files uploaded (and total bytes), new members, active members (distinct senders), session connections/disconnections, kicks, bans, total registered members, users online now, and peak concurrent online. Reports also stream into the live server-logs room, and old ones are pruned past a configurable retention. New Stats config section (Stats:Enabled, Stats:IntervalHours = 6, Stats:RetentionDays = 90). Upload logging — every file, image, and audio upload is now logged with its resource URL (/api/files/{id}), kind, size, uploader, and channel. In end-to-end encrypted rooms the filename is client-side ciphertext, so it's logged as [encrypted] — the server still never sees room content. Moderation & user-action logging — role changes, kicks, bans, unbans, mutes, unmutes, moderator message removals, and channel nukes are now logged with the actor, target, and reason. Bans and channel nukes log at Warning level so they stand out. Improvements Quieter connection logs — user connect, disconnect, join-channel, and leave-channel events (over both SignalR and IRC) dropped from Information to Debug. On a busy server these fired constantly and buried everything else; the aggregate counts now live in the periodic stats report instead. They still show in Development, where the default level is Debug. Config examples stay in sync — .env.example gained the ServerLogs and Stats sections (the former had been missing), alongside appsettings.json / appsettings.example.json. Notes for server operators New config section: Stats — Enabled (default true), IntervalHours (default 6), RetentionDays (default 90, 0 keeps reports forever). See appsettings.example.json and .env.example. A non-positive interval falls back to 6h; positive values are honored down to a 1-second floor. One new database migration (AddServerStatsReports) applies automatically on startup. Connect/disconnect/join/leave now log at Debug — if you relied on those Information lines, lower Serilog:MinimumLevel:Default (or ServerLogs:MinLevel for the room) to Debug, or read the periodic stats report for aggregates." + }, "changelog/v0.2.2.html": { "href": "changelog/v0.2.2.html", "title": "v0.2.2 - Startup & Shutdown Fixes | EchoHub Documentation", diff --git a/manifest.json b/manifest.json index 5e640bf..7f48c44 100644 --- a/manifest.json +++ b/manifest.json @@ -1942,6 +1942,20 @@ "Title": "EchoHub.Core.Models.ServerRole", "Summary": null }, + { + "type": "ManagedReference", + "source_relative_path": "_api_meta/core/EchoHub.Core.Models.ServerStatsReport.yml", + "output": { + ".html": { + "relative_path": "api/core/EchoHub.Core.Models.ServerStatsReport.html" + } + }, + "version": "", + "Uid": null, + "IsMRef": true, + "Title": "EchoHub.Core.Models.ServerStatsReport", + "Summary": "

      A snapshot of server activity over one reporting window, produced periodically by the\nstats-report background job. Each report is logged as pretty-printed JSON and persisted\nfor historical trend analysis. The window is "since the previous report" (or since startup\nfor the first report of a run).

      \n" + }, { "type": "ManagedReference", "source_relative_path": "_api_meta/core/EchoHub.Core.Models.User.yml", @@ -2278,6 +2292,20 @@ "Title": "EchoHub.Server.Config.SpamOptions", "Summary": "

      Anti-spam thresholds, bound from the "Spam" config section. Defaults are lenient enough\nthat a fast typist never trips them; Mods and above are always exempt.

      \n" }, + { + "type": "ManagedReference", + "source_relative_path": "_api_meta/server/EchoHub.Server.Config.StatsOptions.yml", + "output": { + ".html": { + "relative_path": "api/server/EchoHub.Server.Config.StatsOptions.html" + } + }, + "version": "", + "Uid": null, + "IsMRef": true, + "Title": "EchoHub.Server.Config.StatsOptions", + "Summary": "

      Periodic server-stats report settings, bound from the "Stats" config section (env override:\nStats__Enabled etc.). When enabled, a background job periodically snapshots server\nactivity, logs it as pretty-printed JSON, and persists it to the database.

      \n" + }, { "type": "ManagedReference", "source_relative_path": "_api_meta/server/EchoHub.Server.Config.UploadLimits.yml", @@ -2586,6 +2614,20 @@ "Title": "EchoHub.Server.Data.Migrations.AddModerationRoles", "Summary": null }, + { + "type": "ManagedReference", + "source_relative_path": "_api_meta/server/EchoHub.Server.Data.Migrations.AddServerStatsReports.yml", + "output": { + ".html": { + "relative_path": "api/server/EchoHub.Server.Data.Migrations.AddServerStatsReports.html" + } + }, + "version": "", + "Uid": null, + "IsMRef": true, + "Title": "EchoHub.Server.Data.Migrations.AddServerStatsReports", + "Summary": null + }, { "type": "ManagedReference", "source_relative_path": "_api_meta/server/EchoHub.Server.Data.Migrations.InitialCreate.yml", @@ -2936,6 +2978,62 @@ "Title": "EchoHub.Server.Services.SpamVerdictKind", "Summary": null }, + { + "type": "ManagedReference", + "source_relative_path": "_api_meta/server/EchoHub.Server.Services.Stats.ServerStatsCollector.yml", + "output": { + ".html": { + "relative_path": "api/server/EchoHub.Server.Services.Stats.ServerStatsCollector.html" + } + }, + "version": "", + "Uid": null, + "IsMRef": true, + "Title": "EchoHub.Server.Services.Stats.ServerStatsCollector", + "Summary": "

      Thread-safe, in-memory accumulator for server-activity counters that have no natural\ndatabase timestamp to query after the fact — session connects/disconnects, moderation\nactions, and peak concurrency. The periodic stats-report job snapshots and resets these\nonce per reporting window. Registered as a singleton; every increment is lock-free so it\nis safe to call from hot paths (connect/disconnect).

      \n" + }, + { + "type": "ManagedReference", + "source_relative_path": "_api_meta/server/EchoHub.Server.Services.Stats.ServerStatsReportService.yml", + "output": { + ".html": { + "relative_path": "api/server/EchoHub.Server.Services.Stats.ServerStatsReportService.html" + } + }, + "version": "", + "Uid": null, + "IsMRef": true, + "Title": "EchoHub.Server.Services.Stats.ServerStatsReportService", + "Summary": "

      Background job that periodically snapshots server activity over a window, logs it as\npretty-printed JSON (which also surfaces in the live server-logs room), and persists it to\nthe database for historical trends. Interval and retention are configurable via the "Stats"\nsection; the default cadence is every 6 hours.

      \n" + }, + { + "type": "ManagedReference", + "source_relative_path": "_api_meta/server/EchoHub.Server.Services.Stats.StatsCounters.yml", + "output": { + ".html": { + "relative_path": "api/server/EchoHub.Server.Services.Stats.StatsCounters.html" + } + }, + "version": "", + "Uid": null, + "IsMRef": true, + "Title": "EchoHub.Server.Services.Stats.StatsCounters", + "Summary": "

      Immutable snapshot of the counters held by .

      \n" + }, + { + "type": "ManagedReference", + "source_relative_path": "_api_meta/server/EchoHub.Server.Services.Stats.yml", + "output": { + ".html": { + "relative_path": "api/server/EchoHub.Server.Services.Stats.html" + } + }, + "version": "", + "Uid": null, + "IsMRef": true, + "Title": "EchoHub.Server.Services.Stats", + "Summary": null + }, { "type": "ManagedReference", "source_relative_path": "_api_meta/server/EchoHub.Server.Services.UserService.yml", @@ -3368,6 +3466,16 @@ }, "version": "" }, + { + "type": "Conceptual", + "source_relative_path": "changelog/v0.2.16.md", + "output": { + ".html": { + "relative_path": "changelog/v0.2.16.html" + } + }, + "version": "" + }, { "type": "Conceptual", "source_relative_path": "changelog/v0.2.2.md", diff --git a/xrefmap.yml b/xrefmap.yml index e653269..17d0219 100644 --- a/xrefmap.yml +++ b/xrefmap.yml @@ -18250,6 +18250,234 @@ references: commentId: F:EchoHub.Core.Models.ServerRole.Owner fullName: EchoHub.Core.Models.ServerRole.Owner nameWithType: ServerRole.Owner +- uid: EchoHub.Core.Models.ServerStatsReport + name: ServerStatsReport + href: api/core/EchoHub.Core.Models.ServerStatsReport.html + commentId: T:EchoHub.Core.Models.ServerStatsReport + fullName: EchoHub.Core.Models.ServerStatsReport + nameWithType: ServerStatsReport +- uid: EchoHub.Core.Models.ServerStatsReport.#ctor + name: ServerStatsReport() + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport__ctor + commentId: M:EchoHub.Core.Models.ServerStatsReport.#ctor + name.vb: New() + fullName: EchoHub.Core.Models.ServerStatsReport.ServerStatsReport() + fullName.vb: EchoHub.Core.Models.ServerStatsReport.New() + nameWithType: ServerStatsReport.ServerStatsReport() + nameWithType.vb: ServerStatsReport.New() +- uid: EchoHub.Core.Models.ServerStatsReport.#ctor* + name: ServerStatsReport + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport__ctor_ + commentId: Overload:EchoHub.Core.Models.ServerStatsReport.#ctor + name.vb: New + fullName: EchoHub.Core.Models.ServerStatsReport.ServerStatsReport + fullName.vb: EchoHub.Core.Models.ServerStatsReport.New + nameWithType: ServerStatsReport.ServerStatsReport + nameWithType.vb: ServerStatsReport.New +- uid: EchoHub.Core.Models.ServerStatsReport.ActiveMembers + name: ActiveMembers + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_ActiveMembers + commentId: P:EchoHub.Core.Models.ServerStatsReport.ActiveMembers + fullName: EchoHub.Core.Models.ServerStatsReport.ActiveMembers + nameWithType: ServerStatsReport.ActiveMembers +- uid: EchoHub.Core.Models.ServerStatsReport.ActiveMembers* + name: ActiveMembers + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_ActiveMembers_ + commentId: Overload:EchoHub.Core.Models.ServerStatsReport.ActiveMembers + fullName: EchoHub.Core.Models.ServerStatsReport.ActiveMembers + nameWithType: ServerStatsReport.ActiveMembers +- uid: EchoHub.Core.Models.ServerStatsReport.Bans + name: Bans + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_Bans + commentId: P:EchoHub.Core.Models.ServerStatsReport.Bans + fullName: EchoHub.Core.Models.ServerStatsReport.Bans + nameWithType: ServerStatsReport.Bans +- uid: EchoHub.Core.Models.ServerStatsReport.Bans* + name: Bans + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_Bans_ + commentId: Overload:EchoHub.Core.Models.ServerStatsReport.Bans + fullName: EchoHub.Core.Models.ServerStatsReport.Bans + nameWithType: ServerStatsReport.Bans +- uid: EchoHub.Core.Models.ServerStatsReport.BytesUploaded + name: BytesUploaded + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_BytesUploaded + commentId: P:EchoHub.Core.Models.ServerStatsReport.BytesUploaded + fullName: EchoHub.Core.Models.ServerStatsReport.BytesUploaded + nameWithType: ServerStatsReport.BytesUploaded +- uid: EchoHub.Core.Models.ServerStatsReport.BytesUploaded* + name: BytesUploaded + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_BytesUploaded_ + commentId: Overload:EchoHub.Core.Models.ServerStatsReport.BytesUploaded + fullName: EchoHub.Core.Models.ServerStatsReport.BytesUploaded + nameWithType: ServerStatsReport.BytesUploaded +- uid: EchoHub.Core.Models.ServerStatsReport.Connections + name: Connections + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_Connections + commentId: P:EchoHub.Core.Models.ServerStatsReport.Connections + fullName: EchoHub.Core.Models.ServerStatsReport.Connections + nameWithType: ServerStatsReport.Connections +- uid: EchoHub.Core.Models.ServerStatsReport.Connections* + name: Connections + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_Connections_ + commentId: Overload:EchoHub.Core.Models.ServerStatsReport.Connections + fullName: EchoHub.Core.Models.ServerStatsReport.Connections + nameWithType: ServerStatsReport.Connections +- uid: EchoHub.Core.Models.ServerStatsReport.Disconnections + name: Disconnections + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_Disconnections + commentId: P:EchoHub.Core.Models.ServerStatsReport.Disconnections + fullName: EchoHub.Core.Models.ServerStatsReport.Disconnections + nameWithType: ServerStatsReport.Disconnections +- uid: EchoHub.Core.Models.ServerStatsReport.Disconnections* + name: Disconnections + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_Disconnections_ + commentId: Overload:EchoHub.Core.Models.ServerStatsReport.Disconnections + fullName: EchoHub.Core.Models.ServerStatsReport.Disconnections + nameWithType: ServerStatsReport.Disconnections +- uid: EchoHub.Core.Models.ServerStatsReport.FilesUploaded + name: FilesUploaded + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_FilesUploaded + commentId: P:EchoHub.Core.Models.ServerStatsReport.FilesUploaded + fullName: EchoHub.Core.Models.ServerStatsReport.FilesUploaded + nameWithType: ServerStatsReport.FilesUploaded +- uid: EchoHub.Core.Models.ServerStatsReport.FilesUploaded* + name: FilesUploaded + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_FilesUploaded_ + commentId: Overload:EchoHub.Core.Models.ServerStatsReport.FilesUploaded + fullName: EchoHub.Core.Models.ServerStatsReport.FilesUploaded + nameWithType: ServerStatsReport.FilesUploaded +- uid: EchoHub.Core.Models.ServerStatsReport.GeneratedAt + name: GeneratedAt + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_GeneratedAt + commentId: P:EchoHub.Core.Models.ServerStatsReport.GeneratedAt + fullName: EchoHub.Core.Models.ServerStatsReport.GeneratedAt + nameWithType: ServerStatsReport.GeneratedAt +- uid: EchoHub.Core.Models.ServerStatsReport.GeneratedAt* + name: GeneratedAt + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_GeneratedAt_ + commentId: Overload:EchoHub.Core.Models.ServerStatsReport.GeneratedAt + fullName: EchoHub.Core.Models.ServerStatsReport.GeneratedAt + nameWithType: ServerStatsReport.GeneratedAt +- uid: EchoHub.Core.Models.ServerStatsReport.Id + name: Id + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_Id + commentId: P:EchoHub.Core.Models.ServerStatsReport.Id + fullName: EchoHub.Core.Models.ServerStatsReport.Id + nameWithType: ServerStatsReport.Id +- uid: EchoHub.Core.Models.ServerStatsReport.Id* + name: Id + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_Id_ + commentId: Overload:EchoHub.Core.Models.ServerStatsReport.Id + fullName: EchoHub.Core.Models.ServerStatsReport.Id + nameWithType: ServerStatsReport.Id +- uid: EchoHub.Core.Models.ServerStatsReport.Kicks + name: Kicks + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_Kicks + commentId: P:EchoHub.Core.Models.ServerStatsReport.Kicks + fullName: EchoHub.Core.Models.ServerStatsReport.Kicks + nameWithType: ServerStatsReport.Kicks +- uid: EchoHub.Core.Models.ServerStatsReport.Kicks* + name: Kicks + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_Kicks_ + commentId: Overload:EchoHub.Core.Models.ServerStatsReport.Kicks + fullName: EchoHub.Core.Models.ServerStatsReport.Kicks + nameWithType: ServerStatsReport.Kicks +- uid: EchoHub.Core.Models.ServerStatsReport.MessagesSent + name: MessagesSent + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_MessagesSent + commentId: P:EchoHub.Core.Models.ServerStatsReport.MessagesSent + fullName: EchoHub.Core.Models.ServerStatsReport.MessagesSent + nameWithType: ServerStatsReport.MessagesSent +- uid: EchoHub.Core.Models.ServerStatsReport.MessagesSent* + name: MessagesSent + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_MessagesSent_ + commentId: Overload:EchoHub.Core.Models.ServerStatsReport.MessagesSent + fullName: EchoHub.Core.Models.ServerStatsReport.MessagesSent + nameWithType: ServerStatsReport.MessagesSent +- uid: EchoHub.Core.Models.ServerStatsReport.NewMembers + name: NewMembers + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_NewMembers + commentId: P:EchoHub.Core.Models.ServerStatsReport.NewMembers + fullName: EchoHub.Core.Models.ServerStatsReport.NewMembers + nameWithType: ServerStatsReport.NewMembers +- uid: EchoHub.Core.Models.ServerStatsReport.NewMembers* + name: NewMembers + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_NewMembers_ + commentId: Overload:EchoHub.Core.Models.ServerStatsReport.NewMembers + fullName: EchoHub.Core.Models.ServerStatsReport.NewMembers + nameWithType: ServerStatsReport.NewMembers +- uid: EchoHub.Core.Models.ServerStatsReport.OnlineNow + name: OnlineNow + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_OnlineNow + commentId: P:EchoHub.Core.Models.ServerStatsReport.OnlineNow + fullName: EchoHub.Core.Models.ServerStatsReport.OnlineNow + nameWithType: ServerStatsReport.OnlineNow +- uid: EchoHub.Core.Models.ServerStatsReport.OnlineNow* + name: OnlineNow + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_OnlineNow_ + commentId: Overload:EchoHub.Core.Models.ServerStatsReport.OnlineNow + fullName: EchoHub.Core.Models.ServerStatsReport.OnlineNow + nameWithType: ServerStatsReport.OnlineNow +- uid: EchoHub.Core.Models.ServerStatsReport.PeakOnline + name: PeakOnline + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_PeakOnline + commentId: P:EchoHub.Core.Models.ServerStatsReport.PeakOnline + fullName: EchoHub.Core.Models.ServerStatsReport.PeakOnline + nameWithType: ServerStatsReport.PeakOnline +- uid: EchoHub.Core.Models.ServerStatsReport.PeakOnline* + name: PeakOnline + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_PeakOnline_ + commentId: Overload:EchoHub.Core.Models.ServerStatsReport.PeakOnline + fullName: EchoHub.Core.Models.ServerStatsReport.PeakOnline + nameWithType: ServerStatsReport.PeakOnline +- uid: EchoHub.Core.Models.ServerStatsReport.PeriodEnd + name: PeriodEnd + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_PeriodEnd + commentId: P:EchoHub.Core.Models.ServerStatsReport.PeriodEnd + fullName: EchoHub.Core.Models.ServerStatsReport.PeriodEnd + nameWithType: ServerStatsReport.PeriodEnd +- uid: EchoHub.Core.Models.ServerStatsReport.PeriodEnd* + name: PeriodEnd + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_PeriodEnd_ + commentId: Overload:EchoHub.Core.Models.ServerStatsReport.PeriodEnd + fullName: EchoHub.Core.Models.ServerStatsReport.PeriodEnd + nameWithType: ServerStatsReport.PeriodEnd +- uid: EchoHub.Core.Models.ServerStatsReport.PeriodStart + name: PeriodStart + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_PeriodStart + commentId: P:EchoHub.Core.Models.ServerStatsReport.PeriodStart + fullName: EchoHub.Core.Models.ServerStatsReport.PeriodStart + nameWithType: ServerStatsReport.PeriodStart +- uid: EchoHub.Core.Models.ServerStatsReport.PeriodStart* + name: PeriodStart + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_PeriodStart_ + commentId: Overload:EchoHub.Core.Models.ServerStatsReport.PeriodStart + fullName: EchoHub.Core.Models.ServerStatsReport.PeriodStart + nameWithType: ServerStatsReport.PeriodStart +- uid: EchoHub.Core.Models.ServerStatsReport.TotalMembers + name: TotalMembers + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_TotalMembers + commentId: P:EchoHub.Core.Models.ServerStatsReport.TotalMembers + fullName: EchoHub.Core.Models.ServerStatsReport.TotalMembers + nameWithType: ServerStatsReport.TotalMembers +- uid: EchoHub.Core.Models.ServerStatsReport.TotalMembers* + name: TotalMembers + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_TotalMembers_ + commentId: Overload:EchoHub.Core.Models.ServerStatsReport.TotalMembers + fullName: EchoHub.Core.Models.ServerStatsReport.TotalMembers + nameWithType: ServerStatsReport.TotalMembers +- uid: EchoHub.Core.Models.ServerStatsReport.WindowHours + name: WindowHours + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_WindowHours + commentId: P:EchoHub.Core.Models.ServerStatsReport.WindowHours + fullName: EchoHub.Core.Models.ServerStatsReport.WindowHours + nameWithType: ServerStatsReport.WindowHours +- uid: EchoHub.Core.Models.ServerStatsReport.WindowHours* + name: WindowHours + href: api/core/EchoHub.Core.Models.ServerStatsReport.html#EchoHub_Core_Models_ServerStatsReport_WindowHours_ + commentId: Overload:EchoHub.Core.Models.ServerStatsReport.WindowHours + fullName: EchoHub.Core.Models.ServerStatsReport.WindowHours + nameWithType: ServerStatsReport.WindowHours - uid: EchoHub.Core.Models.User name: User href: api/core/EchoHub.Core.Models.User.html @@ -19276,6 +19504,66 @@ references: commentId: Overload:EchoHub.Server.Config.SpamOptions.WindowSeconds fullName: EchoHub.Server.Config.SpamOptions.WindowSeconds nameWithType: SpamOptions.WindowSeconds +- uid: EchoHub.Server.Config.StatsOptions + name: StatsOptions + href: api/server/EchoHub.Server.Config.StatsOptions.html + commentId: T:EchoHub.Server.Config.StatsOptions + fullName: EchoHub.Server.Config.StatsOptions + nameWithType: StatsOptions +- uid: EchoHub.Server.Config.StatsOptions.#ctor + name: StatsOptions() + href: api/server/EchoHub.Server.Config.StatsOptions.html#EchoHub_Server_Config_StatsOptions__ctor + commentId: M:EchoHub.Server.Config.StatsOptions.#ctor + name.vb: New() + fullName: EchoHub.Server.Config.StatsOptions.StatsOptions() + fullName.vb: EchoHub.Server.Config.StatsOptions.New() + nameWithType: StatsOptions.StatsOptions() + nameWithType.vb: StatsOptions.New() +- uid: EchoHub.Server.Config.StatsOptions.#ctor* + name: StatsOptions + href: api/server/EchoHub.Server.Config.StatsOptions.html#EchoHub_Server_Config_StatsOptions__ctor_ + commentId: Overload:EchoHub.Server.Config.StatsOptions.#ctor + name.vb: New + fullName: EchoHub.Server.Config.StatsOptions.StatsOptions + fullName.vb: EchoHub.Server.Config.StatsOptions.New + nameWithType: StatsOptions.StatsOptions + nameWithType.vb: StatsOptions.New +- uid: EchoHub.Server.Config.StatsOptions.Enabled + name: Enabled + href: api/server/EchoHub.Server.Config.StatsOptions.html#EchoHub_Server_Config_StatsOptions_Enabled + commentId: P:EchoHub.Server.Config.StatsOptions.Enabled + fullName: EchoHub.Server.Config.StatsOptions.Enabled + nameWithType: StatsOptions.Enabled +- uid: EchoHub.Server.Config.StatsOptions.Enabled* + name: Enabled + href: api/server/EchoHub.Server.Config.StatsOptions.html#EchoHub_Server_Config_StatsOptions_Enabled_ + commentId: Overload:EchoHub.Server.Config.StatsOptions.Enabled + fullName: EchoHub.Server.Config.StatsOptions.Enabled + nameWithType: StatsOptions.Enabled +- uid: EchoHub.Server.Config.StatsOptions.IntervalHours + name: IntervalHours + href: api/server/EchoHub.Server.Config.StatsOptions.html#EchoHub_Server_Config_StatsOptions_IntervalHours + commentId: P:EchoHub.Server.Config.StatsOptions.IntervalHours + fullName: EchoHub.Server.Config.StatsOptions.IntervalHours + nameWithType: StatsOptions.IntervalHours +- uid: EchoHub.Server.Config.StatsOptions.IntervalHours* + name: IntervalHours + href: api/server/EchoHub.Server.Config.StatsOptions.html#EchoHub_Server_Config_StatsOptions_IntervalHours_ + commentId: Overload:EchoHub.Server.Config.StatsOptions.IntervalHours + fullName: EchoHub.Server.Config.StatsOptions.IntervalHours + nameWithType: StatsOptions.IntervalHours +- uid: EchoHub.Server.Config.StatsOptions.RetentionDays + name: RetentionDays + href: api/server/EchoHub.Server.Config.StatsOptions.html#EchoHub_Server_Config_StatsOptions_RetentionDays + commentId: P:EchoHub.Server.Config.StatsOptions.RetentionDays + fullName: EchoHub.Server.Config.StatsOptions.RetentionDays + nameWithType: StatsOptions.RetentionDays +- uid: EchoHub.Server.Config.StatsOptions.RetentionDays* + name: RetentionDays + href: api/server/EchoHub.Server.Config.StatsOptions.html#EchoHub_Server_Config_StatsOptions_RetentionDays_ + commentId: Overload:EchoHub.Server.Config.StatsOptions.RetentionDays + fullName: EchoHub.Server.Config.StatsOptions.RetentionDays + nameWithType: StatsOptions.RetentionDays - uid: EchoHub.Server.Config.UploadLimits name: UploadLimits href: api/server/EchoHub.Server.Config.UploadLimits.html @@ -19516,15 +19804,15 @@ references: commentId: T:EchoHub.Server.Controllers.ChannelsController fullName: EchoHub.Server.Controllers.ChannelsController nameWithType: ChannelsController -- uid: EchoHub.Server.Controllers.ChannelsController.#ctor(EchoHub.Core.Contracts.IChannelService,EchoHub.Server.Data.EchoHubDbContext,EchoHub.Server.Services.FileStorageService,EchoHub.Core.Services.ImageToAsciiService,System.Net.Http.IHttpClientFactory,EchoHub.Core.Contracts.IChatService,EchoHub.Core.Contracts.IMessageEncryptionService,EchoHub.Server.Config.UploadLimits) - name: ChannelsController(IChannelService, EchoHubDbContext, FileStorageService, ImageToAsciiService, IHttpClientFactory, IChatService, IMessageEncryptionService, UploadLimits) - href: api/server/EchoHub.Server.Controllers.ChannelsController.html#EchoHub_Server_Controllers_ChannelsController__ctor_EchoHub_Core_Contracts_IChannelService_EchoHub_Server_Data_EchoHubDbContext_EchoHub_Server_Services_FileStorageService_EchoHub_Core_Services_ImageToAsciiService_System_Net_Http_IHttpClientFactory_EchoHub_Core_Contracts_IChatService_EchoHub_Core_Contracts_IMessageEncryptionService_EchoHub_Server_Config_UploadLimits_ - commentId: M:EchoHub.Server.Controllers.ChannelsController.#ctor(EchoHub.Core.Contracts.IChannelService,EchoHub.Server.Data.EchoHubDbContext,EchoHub.Server.Services.FileStorageService,EchoHub.Core.Services.ImageToAsciiService,System.Net.Http.IHttpClientFactory,EchoHub.Core.Contracts.IChatService,EchoHub.Core.Contracts.IMessageEncryptionService,EchoHub.Server.Config.UploadLimits) - name.vb: New(IChannelService, EchoHubDbContext, FileStorageService, ImageToAsciiService, IHttpClientFactory, IChatService, IMessageEncryptionService, UploadLimits) - fullName: EchoHub.Server.Controllers.ChannelsController.ChannelsController(EchoHub.Core.Contracts.IChannelService, EchoHub.Server.Data.EchoHubDbContext, EchoHub.Server.Services.FileStorageService, EchoHub.Core.Services.ImageToAsciiService, System.Net.Http.IHttpClientFactory, EchoHub.Core.Contracts.IChatService, EchoHub.Core.Contracts.IMessageEncryptionService, EchoHub.Server.Config.UploadLimits) - fullName.vb: EchoHub.Server.Controllers.ChannelsController.New(EchoHub.Core.Contracts.IChannelService, EchoHub.Server.Data.EchoHubDbContext, EchoHub.Server.Services.FileStorageService, EchoHub.Core.Services.ImageToAsciiService, System.Net.Http.IHttpClientFactory, EchoHub.Core.Contracts.IChatService, EchoHub.Core.Contracts.IMessageEncryptionService, EchoHub.Server.Config.UploadLimits) - nameWithType: ChannelsController.ChannelsController(IChannelService, EchoHubDbContext, FileStorageService, ImageToAsciiService, IHttpClientFactory, IChatService, IMessageEncryptionService, UploadLimits) - nameWithType.vb: ChannelsController.New(IChannelService, EchoHubDbContext, FileStorageService, ImageToAsciiService, IHttpClientFactory, IChatService, IMessageEncryptionService, UploadLimits) +- uid: EchoHub.Server.Controllers.ChannelsController.#ctor(EchoHub.Core.Contracts.IChannelService,EchoHub.Server.Data.EchoHubDbContext,EchoHub.Server.Services.FileStorageService,EchoHub.Core.Services.ImageToAsciiService,System.Net.Http.IHttpClientFactory,EchoHub.Core.Contracts.IChatService,EchoHub.Core.Contracts.IMessageEncryptionService,EchoHub.Server.Config.UploadLimits,Microsoft.Extensions.Logging.ILogger{EchoHub.Server.Controllers.ChannelsController}) + name: ChannelsController(IChannelService, EchoHubDbContext, FileStorageService, ImageToAsciiService, IHttpClientFactory, IChatService, IMessageEncryptionService, UploadLimits, ILogger) + href: api/server/EchoHub.Server.Controllers.ChannelsController.html#EchoHub_Server_Controllers_ChannelsController__ctor_EchoHub_Core_Contracts_IChannelService_EchoHub_Server_Data_EchoHubDbContext_EchoHub_Server_Services_FileStorageService_EchoHub_Core_Services_ImageToAsciiService_System_Net_Http_IHttpClientFactory_EchoHub_Core_Contracts_IChatService_EchoHub_Core_Contracts_IMessageEncryptionService_EchoHub_Server_Config_UploadLimits_Microsoft_Extensions_Logging_ILogger_EchoHub_Server_Controllers_ChannelsController__ + commentId: M:EchoHub.Server.Controllers.ChannelsController.#ctor(EchoHub.Core.Contracts.IChannelService,EchoHub.Server.Data.EchoHubDbContext,EchoHub.Server.Services.FileStorageService,EchoHub.Core.Services.ImageToAsciiService,System.Net.Http.IHttpClientFactory,EchoHub.Core.Contracts.IChatService,EchoHub.Core.Contracts.IMessageEncryptionService,EchoHub.Server.Config.UploadLimits,Microsoft.Extensions.Logging.ILogger{EchoHub.Server.Controllers.ChannelsController}) + name.vb: New(IChannelService, EchoHubDbContext, FileStorageService, ImageToAsciiService, IHttpClientFactory, IChatService, IMessageEncryptionService, UploadLimits, ILogger(Of ChannelsController)) + fullName: EchoHub.Server.Controllers.ChannelsController.ChannelsController(EchoHub.Core.Contracts.IChannelService, EchoHub.Server.Data.EchoHubDbContext, EchoHub.Server.Services.FileStorageService, EchoHub.Core.Services.ImageToAsciiService, System.Net.Http.IHttpClientFactory, EchoHub.Core.Contracts.IChatService, EchoHub.Core.Contracts.IMessageEncryptionService, EchoHub.Server.Config.UploadLimits, Microsoft.Extensions.Logging.ILogger) + fullName.vb: EchoHub.Server.Controllers.ChannelsController.New(EchoHub.Core.Contracts.IChannelService, EchoHub.Server.Data.EchoHubDbContext, EchoHub.Server.Services.FileStorageService, EchoHub.Core.Services.ImageToAsciiService, System.Net.Http.IHttpClientFactory, EchoHub.Core.Contracts.IChatService, EchoHub.Core.Contracts.IMessageEncryptionService, EchoHub.Server.Config.UploadLimits, Microsoft.Extensions.Logging.ILogger(Of EchoHub.Server.Controllers.ChannelsController)) + nameWithType: ChannelsController.ChannelsController(IChannelService, EchoHubDbContext, FileStorageService, ImageToAsciiService, IHttpClientFactory, IChatService, IMessageEncryptionService, UploadLimits, ILogger) + nameWithType.vb: ChannelsController.New(IChannelService, EchoHubDbContext, FileStorageService, ImageToAsciiService, IHttpClientFactory, IChatService, IMessageEncryptionService, UploadLimits, ILogger(Of ChannelsController)) - uid: EchoHub.Server.Controllers.ChannelsController.#ctor* name: ChannelsController href: api/server/EchoHub.Server.Controllers.ChannelsController.html#EchoHub_Server_Controllers_ChannelsController__ctor_ @@ -19774,15 +20062,15 @@ references: commentId: T:EchoHub.Server.Controllers.ModerationController fullName: EchoHub.Server.Controllers.ModerationController nameWithType: ModerationController -- uid: EchoHub.Server.Controllers.ModerationController.#ctor(EchoHub.Server.Data.EchoHubDbContext,EchoHub.Core.Contracts.IChatService,EchoHub.Server.Services.PresenceTracker,EchoHub.Server.Services.FileStorageService,System.Collections.Generic.IEnumerable{EchoHub.Core.Contracts.IChatBroadcaster}) - name: ModerationController(EchoHubDbContext, IChatService, PresenceTracker, FileStorageService, IEnumerable) - href: api/server/EchoHub.Server.Controllers.ModerationController.html#EchoHub_Server_Controllers_ModerationController__ctor_EchoHub_Server_Data_EchoHubDbContext_EchoHub_Core_Contracts_IChatService_EchoHub_Server_Services_PresenceTracker_EchoHub_Server_Services_FileStorageService_System_Collections_Generic_IEnumerable_EchoHub_Core_Contracts_IChatBroadcaster__ - commentId: M:EchoHub.Server.Controllers.ModerationController.#ctor(EchoHub.Server.Data.EchoHubDbContext,EchoHub.Core.Contracts.IChatService,EchoHub.Server.Services.PresenceTracker,EchoHub.Server.Services.FileStorageService,System.Collections.Generic.IEnumerable{EchoHub.Core.Contracts.IChatBroadcaster}) - name.vb: New(EchoHubDbContext, IChatService, PresenceTracker, FileStorageService, IEnumerable(Of IChatBroadcaster)) - fullName: EchoHub.Server.Controllers.ModerationController.ModerationController(EchoHub.Server.Data.EchoHubDbContext, EchoHub.Core.Contracts.IChatService, EchoHub.Server.Services.PresenceTracker, EchoHub.Server.Services.FileStorageService, System.Collections.Generic.IEnumerable) - fullName.vb: EchoHub.Server.Controllers.ModerationController.New(EchoHub.Server.Data.EchoHubDbContext, EchoHub.Core.Contracts.IChatService, EchoHub.Server.Services.PresenceTracker, EchoHub.Server.Services.FileStorageService, System.Collections.Generic.IEnumerable(Of EchoHub.Core.Contracts.IChatBroadcaster)) - nameWithType: ModerationController.ModerationController(EchoHubDbContext, IChatService, PresenceTracker, FileStorageService, IEnumerable) - nameWithType.vb: ModerationController.New(EchoHubDbContext, IChatService, PresenceTracker, FileStorageService, IEnumerable(Of IChatBroadcaster)) +- uid: EchoHub.Server.Controllers.ModerationController.#ctor(EchoHub.Server.Data.EchoHubDbContext,EchoHub.Core.Contracts.IChatService,EchoHub.Server.Services.PresenceTracker,EchoHub.Server.Services.FileStorageService,System.Collections.Generic.IEnumerable{EchoHub.Core.Contracts.IChatBroadcaster},EchoHub.Server.Services.Stats.ServerStatsCollector,Microsoft.Extensions.Logging.ILogger{EchoHub.Server.Controllers.ModerationController}) + name: ModerationController(EchoHubDbContext, IChatService, PresenceTracker, FileStorageService, IEnumerable, ServerStatsCollector, ILogger) + href: api/server/EchoHub.Server.Controllers.ModerationController.html#EchoHub_Server_Controllers_ModerationController__ctor_EchoHub_Server_Data_EchoHubDbContext_EchoHub_Core_Contracts_IChatService_EchoHub_Server_Services_PresenceTracker_EchoHub_Server_Services_FileStorageService_System_Collections_Generic_IEnumerable_EchoHub_Core_Contracts_IChatBroadcaster__EchoHub_Server_Services_Stats_ServerStatsCollector_Microsoft_Extensions_Logging_ILogger_EchoHub_Server_Controllers_ModerationController__ + commentId: M:EchoHub.Server.Controllers.ModerationController.#ctor(EchoHub.Server.Data.EchoHubDbContext,EchoHub.Core.Contracts.IChatService,EchoHub.Server.Services.PresenceTracker,EchoHub.Server.Services.FileStorageService,System.Collections.Generic.IEnumerable{EchoHub.Core.Contracts.IChatBroadcaster},EchoHub.Server.Services.Stats.ServerStatsCollector,Microsoft.Extensions.Logging.ILogger{EchoHub.Server.Controllers.ModerationController}) + name.vb: New(EchoHubDbContext, IChatService, PresenceTracker, FileStorageService, IEnumerable(Of IChatBroadcaster), ServerStatsCollector, ILogger(Of ModerationController)) + fullName: EchoHub.Server.Controllers.ModerationController.ModerationController(EchoHub.Server.Data.EchoHubDbContext, EchoHub.Core.Contracts.IChatService, EchoHub.Server.Services.PresenceTracker, EchoHub.Server.Services.FileStorageService, System.Collections.Generic.IEnumerable, EchoHub.Server.Services.Stats.ServerStatsCollector, Microsoft.Extensions.Logging.ILogger) + fullName.vb: EchoHub.Server.Controllers.ModerationController.New(EchoHub.Server.Data.EchoHubDbContext, EchoHub.Core.Contracts.IChatService, EchoHub.Server.Services.PresenceTracker, EchoHub.Server.Services.FileStorageService, System.Collections.Generic.IEnumerable(Of EchoHub.Core.Contracts.IChatBroadcaster), EchoHub.Server.Services.Stats.ServerStatsCollector, Microsoft.Extensions.Logging.ILogger(Of EchoHub.Server.Controllers.ModerationController)) + nameWithType: ModerationController.ModerationController(EchoHubDbContext, IChatService, PresenceTracker, FileStorageService, IEnumerable, ServerStatsCollector, ILogger) + nameWithType.vb: ModerationController.New(EchoHubDbContext, IChatService, PresenceTracker, FileStorageService, IEnumerable(Of IChatBroadcaster), ServerStatsCollector, ILogger(Of ModerationController)) - uid: EchoHub.Server.Controllers.ModerationController.#ctor* name: ModerationController href: api/server/EchoHub.Server.Controllers.ModerationController.html#EchoHub_Server_Controllers_ModerationController__ctor_ @@ -20185,6 +20473,18 @@ references: commentId: Overload:EchoHub.Server.Data.EchoHubDbContext.RefreshTokens fullName: EchoHub.Server.Data.EchoHubDbContext.RefreshTokens nameWithType: EchoHubDbContext.RefreshTokens +- uid: EchoHub.Server.Data.EchoHubDbContext.ServerStatsReports + name: ServerStatsReports + href: api/server/EchoHub.Server.Data.EchoHubDbContext.html#EchoHub_Server_Data_EchoHubDbContext_ServerStatsReports + commentId: P:EchoHub.Server.Data.EchoHubDbContext.ServerStatsReports + fullName: EchoHub.Server.Data.EchoHubDbContext.ServerStatsReports + nameWithType: EchoHubDbContext.ServerStatsReports +- uid: EchoHub.Server.Data.EchoHubDbContext.ServerStatsReports* + name: ServerStatsReports + href: api/server/EchoHub.Server.Data.EchoHubDbContext.html#EchoHub_Server_Data_EchoHubDbContext_ServerStatsReports_ + commentId: Overload:EchoHub.Server.Data.EchoHubDbContext.ServerStatsReports + fullName: EchoHub.Server.Data.EchoHubDbContext.ServerStatsReports + nameWithType: EchoHubDbContext.ServerStatsReports - uid: EchoHub.Server.Data.EchoHubDbContext.Users name: Users href: api/server/EchoHub.Server.Data.EchoHubDbContext.html#EchoHub_Server_Data_EchoHubDbContext_Users @@ -20863,6 +21163,66 @@ references: commentId: Overload:EchoHub.Server.Data.Migrations.AddModerationRoles.Up fullName: EchoHub.Server.Data.Migrations.AddModerationRoles.Up nameWithType: AddModerationRoles.Up +- uid: EchoHub.Server.Data.Migrations.AddServerStatsReports + name: AddServerStatsReports + href: api/server/EchoHub.Server.Data.Migrations.AddServerStatsReports.html + commentId: T:EchoHub.Server.Data.Migrations.AddServerStatsReports + fullName: EchoHub.Server.Data.Migrations.AddServerStatsReports + nameWithType: AddServerStatsReports +- uid: EchoHub.Server.Data.Migrations.AddServerStatsReports.#ctor + name: AddServerStatsReports() + href: api/server/EchoHub.Server.Data.Migrations.AddServerStatsReports.html#EchoHub_Server_Data_Migrations_AddServerStatsReports__ctor + commentId: M:EchoHub.Server.Data.Migrations.AddServerStatsReports.#ctor + name.vb: New() + fullName: EchoHub.Server.Data.Migrations.AddServerStatsReports.AddServerStatsReports() + fullName.vb: EchoHub.Server.Data.Migrations.AddServerStatsReports.New() + nameWithType: AddServerStatsReports.AddServerStatsReports() + nameWithType.vb: AddServerStatsReports.New() +- uid: EchoHub.Server.Data.Migrations.AddServerStatsReports.#ctor* + name: AddServerStatsReports + href: api/server/EchoHub.Server.Data.Migrations.AddServerStatsReports.html#EchoHub_Server_Data_Migrations_AddServerStatsReports__ctor_ + commentId: Overload:EchoHub.Server.Data.Migrations.AddServerStatsReports.#ctor + name.vb: New + fullName: EchoHub.Server.Data.Migrations.AddServerStatsReports.AddServerStatsReports + fullName.vb: EchoHub.Server.Data.Migrations.AddServerStatsReports.New + nameWithType: AddServerStatsReports.AddServerStatsReports + nameWithType.vb: AddServerStatsReports.New +- uid: EchoHub.Server.Data.Migrations.AddServerStatsReports.BuildTargetModel(Microsoft.EntityFrameworkCore.ModelBuilder) + name: BuildTargetModel(ModelBuilder) + href: api/server/EchoHub.Server.Data.Migrations.AddServerStatsReports.html#EchoHub_Server_Data_Migrations_AddServerStatsReports_BuildTargetModel_Microsoft_EntityFrameworkCore_ModelBuilder_ + commentId: M:EchoHub.Server.Data.Migrations.AddServerStatsReports.BuildTargetModel(Microsoft.EntityFrameworkCore.ModelBuilder) + fullName: EchoHub.Server.Data.Migrations.AddServerStatsReports.BuildTargetModel(Microsoft.EntityFrameworkCore.ModelBuilder) + nameWithType: AddServerStatsReports.BuildTargetModel(ModelBuilder) +- uid: EchoHub.Server.Data.Migrations.AddServerStatsReports.BuildTargetModel* + name: BuildTargetModel + href: api/server/EchoHub.Server.Data.Migrations.AddServerStatsReports.html#EchoHub_Server_Data_Migrations_AddServerStatsReports_BuildTargetModel_ + commentId: Overload:EchoHub.Server.Data.Migrations.AddServerStatsReports.BuildTargetModel + fullName: EchoHub.Server.Data.Migrations.AddServerStatsReports.BuildTargetModel + nameWithType: AddServerStatsReports.BuildTargetModel +- uid: EchoHub.Server.Data.Migrations.AddServerStatsReports.Down(Microsoft.EntityFrameworkCore.Migrations.MigrationBuilder) + name: Down(MigrationBuilder) + href: api/server/EchoHub.Server.Data.Migrations.AddServerStatsReports.html#EchoHub_Server_Data_Migrations_AddServerStatsReports_Down_Microsoft_EntityFrameworkCore_Migrations_MigrationBuilder_ + commentId: M:EchoHub.Server.Data.Migrations.AddServerStatsReports.Down(Microsoft.EntityFrameworkCore.Migrations.MigrationBuilder) + fullName: EchoHub.Server.Data.Migrations.AddServerStatsReports.Down(Microsoft.EntityFrameworkCore.Migrations.MigrationBuilder) + nameWithType: AddServerStatsReports.Down(MigrationBuilder) +- uid: EchoHub.Server.Data.Migrations.AddServerStatsReports.Down* + name: Down + href: api/server/EchoHub.Server.Data.Migrations.AddServerStatsReports.html#EchoHub_Server_Data_Migrations_AddServerStatsReports_Down_ + commentId: Overload:EchoHub.Server.Data.Migrations.AddServerStatsReports.Down + fullName: EchoHub.Server.Data.Migrations.AddServerStatsReports.Down + nameWithType: AddServerStatsReports.Down +- uid: EchoHub.Server.Data.Migrations.AddServerStatsReports.Up(Microsoft.EntityFrameworkCore.Migrations.MigrationBuilder) + name: Up(MigrationBuilder) + href: api/server/EchoHub.Server.Data.Migrations.AddServerStatsReports.html#EchoHub_Server_Data_Migrations_AddServerStatsReports_Up_Microsoft_EntityFrameworkCore_Migrations_MigrationBuilder_ + commentId: M:EchoHub.Server.Data.Migrations.AddServerStatsReports.Up(Microsoft.EntityFrameworkCore.Migrations.MigrationBuilder) + fullName: EchoHub.Server.Data.Migrations.AddServerStatsReports.Up(Microsoft.EntityFrameworkCore.Migrations.MigrationBuilder) + nameWithType: AddServerStatsReports.Up(MigrationBuilder) +- uid: EchoHub.Server.Data.Migrations.AddServerStatsReports.Up* + name: Up + href: api/server/EchoHub.Server.Data.Migrations.AddServerStatsReports.html#EchoHub_Server_Data_Migrations_AddServerStatsReports_Up_ + commentId: Overload:EchoHub.Server.Data.Migrations.AddServerStatsReports.Up + fullName: EchoHub.Server.Data.Migrations.AddServerStatsReports.Up + nameWithType: AddServerStatsReports.Up - uid: EchoHub.Server.Data.Migrations.InitialCreate name: InitialCreate href: api/server/EchoHub.Server.Data.Migrations.InitialCreate.html @@ -22528,15 +22888,15 @@ references: commentId: T:EchoHub.Server.Services.ChatService fullName: EchoHub.Server.Services.ChatService nameWithType: ChatService -- uid: EchoHub.Server.Services.ChatService.#ctor(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory,EchoHub.Server.Services.PresenceTracker,System.Collections.Generic.IEnumerable{EchoHub.Core.Contracts.IChatBroadcaster},EchoHub.Server.Services.LinkEmbedService,EchoHub.Core.Contracts.IMessageEncryptionService,EchoHub.Core.Contracts.IChannelService,EchoHub.Server.Services.FileStorageService,EchoHub.Server.Services.SpamGuard,EchoHub.Server.Services.ServerLogs.ServerLogsService,Microsoft.Extensions.Logging.ILogger{EchoHub.Server.Services.ChatService}) - name: ChatService(IServiceScopeFactory, PresenceTracker, IEnumerable, LinkEmbedService, IMessageEncryptionService, IChannelService, FileStorageService, SpamGuard, ServerLogsService, ILogger) - href: api/server/EchoHub.Server.Services.ChatService.html#EchoHub_Server_Services_ChatService__ctor_Microsoft_Extensions_DependencyInjection_IServiceScopeFactory_EchoHub_Server_Services_PresenceTracker_System_Collections_Generic_IEnumerable_EchoHub_Core_Contracts_IChatBroadcaster__EchoHub_Server_Services_LinkEmbedService_EchoHub_Core_Contracts_IMessageEncryptionService_EchoHub_Core_Contracts_IChannelService_EchoHub_Server_Services_FileStorageService_EchoHub_Server_Services_SpamGuard_EchoHub_Server_Services_ServerLogs_ServerLogsService_Microsoft_Extensions_Logging_ILogger_EchoHub_Server_Services_ChatService__ - commentId: M:EchoHub.Server.Services.ChatService.#ctor(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory,EchoHub.Server.Services.PresenceTracker,System.Collections.Generic.IEnumerable{EchoHub.Core.Contracts.IChatBroadcaster},EchoHub.Server.Services.LinkEmbedService,EchoHub.Core.Contracts.IMessageEncryptionService,EchoHub.Core.Contracts.IChannelService,EchoHub.Server.Services.FileStorageService,EchoHub.Server.Services.SpamGuard,EchoHub.Server.Services.ServerLogs.ServerLogsService,Microsoft.Extensions.Logging.ILogger{EchoHub.Server.Services.ChatService}) - name.vb: New(IServiceScopeFactory, PresenceTracker, IEnumerable(Of IChatBroadcaster), LinkEmbedService, IMessageEncryptionService, IChannelService, FileStorageService, SpamGuard, ServerLogsService, ILogger(Of ChatService)) - fullName: EchoHub.Server.Services.ChatService.ChatService(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory, EchoHub.Server.Services.PresenceTracker, System.Collections.Generic.IEnumerable, EchoHub.Server.Services.LinkEmbedService, EchoHub.Core.Contracts.IMessageEncryptionService, EchoHub.Core.Contracts.IChannelService, EchoHub.Server.Services.FileStorageService, EchoHub.Server.Services.SpamGuard, EchoHub.Server.Services.ServerLogs.ServerLogsService, Microsoft.Extensions.Logging.ILogger) - fullName.vb: EchoHub.Server.Services.ChatService.New(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory, EchoHub.Server.Services.PresenceTracker, System.Collections.Generic.IEnumerable(Of EchoHub.Core.Contracts.IChatBroadcaster), EchoHub.Server.Services.LinkEmbedService, EchoHub.Core.Contracts.IMessageEncryptionService, EchoHub.Core.Contracts.IChannelService, EchoHub.Server.Services.FileStorageService, EchoHub.Server.Services.SpamGuard, EchoHub.Server.Services.ServerLogs.ServerLogsService, Microsoft.Extensions.Logging.ILogger(Of EchoHub.Server.Services.ChatService)) - nameWithType: ChatService.ChatService(IServiceScopeFactory, PresenceTracker, IEnumerable, LinkEmbedService, IMessageEncryptionService, IChannelService, FileStorageService, SpamGuard, ServerLogsService, ILogger) - nameWithType.vb: ChatService.New(IServiceScopeFactory, PresenceTracker, IEnumerable(Of IChatBroadcaster), LinkEmbedService, IMessageEncryptionService, IChannelService, FileStorageService, SpamGuard, ServerLogsService, ILogger(Of ChatService)) +- uid: EchoHub.Server.Services.ChatService.#ctor(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory,EchoHub.Server.Services.PresenceTracker,System.Collections.Generic.IEnumerable{EchoHub.Core.Contracts.IChatBroadcaster},EchoHub.Server.Services.LinkEmbedService,EchoHub.Core.Contracts.IMessageEncryptionService,EchoHub.Core.Contracts.IChannelService,EchoHub.Server.Services.FileStorageService,EchoHub.Server.Services.SpamGuard,EchoHub.Server.Services.ServerLogs.ServerLogsService,EchoHub.Server.Services.Stats.ServerStatsCollector,Microsoft.Extensions.Logging.ILogger{EchoHub.Server.Services.ChatService}) + name: ChatService(IServiceScopeFactory, PresenceTracker, IEnumerable, LinkEmbedService, IMessageEncryptionService, IChannelService, FileStorageService, SpamGuard, ServerLogsService, ServerStatsCollector, ILogger) + href: api/server/EchoHub.Server.Services.ChatService.html#EchoHub_Server_Services_ChatService__ctor_Microsoft_Extensions_DependencyInjection_IServiceScopeFactory_EchoHub_Server_Services_PresenceTracker_System_Collections_Generic_IEnumerable_EchoHub_Core_Contracts_IChatBroadcaster__EchoHub_Server_Services_LinkEmbedService_EchoHub_Core_Contracts_IMessageEncryptionService_EchoHub_Core_Contracts_IChannelService_EchoHub_Server_Services_FileStorageService_EchoHub_Server_Services_SpamGuard_EchoHub_Server_Services_ServerLogs_ServerLogsService_EchoHub_Server_Services_Stats_ServerStatsCollector_Microsoft_Extensions_Logging_ILogger_EchoHub_Server_Services_ChatService__ + commentId: M:EchoHub.Server.Services.ChatService.#ctor(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory,EchoHub.Server.Services.PresenceTracker,System.Collections.Generic.IEnumerable{EchoHub.Core.Contracts.IChatBroadcaster},EchoHub.Server.Services.LinkEmbedService,EchoHub.Core.Contracts.IMessageEncryptionService,EchoHub.Core.Contracts.IChannelService,EchoHub.Server.Services.FileStorageService,EchoHub.Server.Services.SpamGuard,EchoHub.Server.Services.ServerLogs.ServerLogsService,EchoHub.Server.Services.Stats.ServerStatsCollector,Microsoft.Extensions.Logging.ILogger{EchoHub.Server.Services.ChatService}) + name.vb: New(IServiceScopeFactory, PresenceTracker, IEnumerable(Of IChatBroadcaster), LinkEmbedService, IMessageEncryptionService, IChannelService, FileStorageService, SpamGuard, ServerLogsService, ServerStatsCollector, ILogger(Of ChatService)) + fullName: EchoHub.Server.Services.ChatService.ChatService(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory, EchoHub.Server.Services.PresenceTracker, System.Collections.Generic.IEnumerable, EchoHub.Server.Services.LinkEmbedService, EchoHub.Core.Contracts.IMessageEncryptionService, EchoHub.Core.Contracts.IChannelService, EchoHub.Server.Services.FileStorageService, EchoHub.Server.Services.SpamGuard, EchoHub.Server.Services.ServerLogs.ServerLogsService, EchoHub.Server.Services.Stats.ServerStatsCollector, Microsoft.Extensions.Logging.ILogger) + fullName.vb: EchoHub.Server.Services.ChatService.New(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory, EchoHub.Server.Services.PresenceTracker, System.Collections.Generic.IEnumerable(Of EchoHub.Core.Contracts.IChatBroadcaster), EchoHub.Server.Services.LinkEmbedService, EchoHub.Core.Contracts.IMessageEncryptionService, EchoHub.Core.Contracts.IChannelService, EchoHub.Server.Services.FileStorageService, EchoHub.Server.Services.SpamGuard, EchoHub.Server.Services.ServerLogs.ServerLogsService, EchoHub.Server.Services.Stats.ServerStatsCollector, Microsoft.Extensions.Logging.ILogger(Of EchoHub.Server.Services.ChatService)) + nameWithType: ChatService.ChatService(IServiceScopeFactory, PresenceTracker, IEnumerable, LinkEmbedService, IMessageEncryptionService, IChannelService, FileStorageService, SpamGuard, ServerLogsService, ServerStatsCollector, ILogger) + nameWithType.vb: ChatService.New(IServiceScopeFactory, PresenceTracker, IEnumerable(Of IChatBroadcaster), LinkEmbedService, IMessageEncryptionService, IChannelService, FileStorageService, SpamGuard, ServerLogsService, ServerStatsCollector, ILogger(Of ChatService)) - uid: EchoHub.Server.Services.ChatService.#ctor* name: ChatService href: api/server/EchoHub.Server.Services.ChatService.html#EchoHub_Server_Services_ChatService__ctor_ @@ -24427,6 +24787,336 @@ references: commentId: F:EchoHub.Server.Services.SpamVerdictKind.Rejected fullName: EchoHub.Server.Services.SpamVerdictKind.Rejected nameWithType: SpamVerdictKind.Rejected +- uid: EchoHub.Server.Services.Stats + name: EchoHub.Server.Services.Stats + href: api/server/EchoHub.Server.Services.Stats.html + commentId: N:EchoHub.Server.Services.Stats + fullName: EchoHub.Server.Services.Stats + nameWithType: EchoHub.Server.Services.Stats +- uid: EchoHub.Server.Services.Stats.ServerStatsCollector + name: ServerStatsCollector + href: api/server/EchoHub.Server.Services.Stats.ServerStatsCollector.html + commentId: T:EchoHub.Server.Services.Stats.ServerStatsCollector + fullName: EchoHub.Server.Services.Stats.ServerStatsCollector + nameWithType: ServerStatsCollector +- uid: EchoHub.Server.Services.Stats.ServerStatsCollector.#ctor + name: ServerStatsCollector() + href: api/server/EchoHub.Server.Services.Stats.ServerStatsCollector.html#EchoHub_Server_Services_Stats_ServerStatsCollector__ctor + commentId: M:EchoHub.Server.Services.Stats.ServerStatsCollector.#ctor + name.vb: New() + fullName: EchoHub.Server.Services.Stats.ServerStatsCollector.ServerStatsCollector() + fullName.vb: EchoHub.Server.Services.Stats.ServerStatsCollector.New() + nameWithType: ServerStatsCollector.ServerStatsCollector() + nameWithType.vb: ServerStatsCollector.New() +- uid: EchoHub.Server.Services.Stats.ServerStatsCollector.#ctor* + name: ServerStatsCollector + href: api/server/EchoHub.Server.Services.Stats.ServerStatsCollector.html#EchoHub_Server_Services_Stats_ServerStatsCollector__ctor_ + commentId: Overload:EchoHub.Server.Services.Stats.ServerStatsCollector.#ctor + name.vb: New + fullName: EchoHub.Server.Services.Stats.ServerStatsCollector.ServerStatsCollector + fullName.vb: EchoHub.Server.Services.Stats.ServerStatsCollector.New + nameWithType: ServerStatsCollector.ServerStatsCollector + nameWithType.vb: ServerStatsCollector.New +- uid: EchoHub.Server.Services.Stats.ServerStatsCollector.RecordBan + name: RecordBan() + href: api/server/EchoHub.Server.Services.Stats.ServerStatsCollector.html#EchoHub_Server_Services_Stats_ServerStatsCollector_RecordBan + commentId: M:EchoHub.Server.Services.Stats.ServerStatsCollector.RecordBan + fullName: EchoHub.Server.Services.Stats.ServerStatsCollector.RecordBan() + nameWithType: ServerStatsCollector.RecordBan() +- uid: EchoHub.Server.Services.Stats.ServerStatsCollector.RecordBan* + name: RecordBan + href: api/server/EchoHub.Server.Services.Stats.ServerStatsCollector.html#EchoHub_Server_Services_Stats_ServerStatsCollector_RecordBan_ + commentId: Overload:EchoHub.Server.Services.Stats.ServerStatsCollector.RecordBan + fullName: EchoHub.Server.Services.Stats.ServerStatsCollector.RecordBan + nameWithType: ServerStatsCollector.RecordBan +- uid: EchoHub.Server.Services.Stats.ServerStatsCollector.RecordConnection(System.Int32) + name: RecordConnection(int) + href: api/server/EchoHub.Server.Services.Stats.ServerStatsCollector.html#EchoHub_Server_Services_Stats_ServerStatsCollector_RecordConnection_System_Int32_ + commentId: M:EchoHub.Server.Services.Stats.ServerStatsCollector.RecordConnection(System.Int32) + name.vb: RecordConnection(Integer) + fullName: EchoHub.Server.Services.Stats.ServerStatsCollector.RecordConnection(int) + fullName.vb: EchoHub.Server.Services.Stats.ServerStatsCollector.RecordConnection(Integer) + nameWithType: ServerStatsCollector.RecordConnection(int) + nameWithType.vb: ServerStatsCollector.RecordConnection(Integer) +- uid: EchoHub.Server.Services.Stats.ServerStatsCollector.RecordConnection* + name: RecordConnection + href: api/server/EchoHub.Server.Services.Stats.ServerStatsCollector.html#EchoHub_Server_Services_Stats_ServerStatsCollector_RecordConnection_ + commentId: Overload:EchoHub.Server.Services.Stats.ServerStatsCollector.RecordConnection + fullName: EchoHub.Server.Services.Stats.ServerStatsCollector.RecordConnection + nameWithType: ServerStatsCollector.RecordConnection +- uid: EchoHub.Server.Services.Stats.ServerStatsCollector.RecordDisconnection(System.Int32) + name: RecordDisconnection(int) + href: api/server/EchoHub.Server.Services.Stats.ServerStatsCollector.html#EchoHub_Server_Services_Stats_ServerStatsCollector_RecordDisconnection_System_Int32_ + commentId: M:EchoHub.Server.Services.Stats.ServerStatsCollector.RecordDisconnection(System.Int32) + name.vb: RecordDisconnection(Integer) + fullName: EchoHub.Server.Services.Stats.ServerStatsCollector.RecordDisconnection(int) + fullName.vb: EchoHub.Server.Services.Stats.ServerStatsCollector.RecordDisconnection(Integer) + nameWithType: ServerStatsCollector.RecordDisconnection(int) + nameWithType.vb: ServerStatsCollector.RecordDisconnection(Integer) +- uid: EchoHub.Server.Services.Stats.ServerStatsCollector.RecordDisconnection* + name: RecordDisconnection + href: api/server/EchoHub.Server.Services.Stats.ServerStatsCollector.html#EchoHub_Server_Services_Stats_ServerStatsCollector_RecordDisconnection_ + commentId: Overload:EchoHub.Server.Services.Stats.ServerStatsCollector.RecordDisconnection + fullName: EchoHub.Server.Services.Stats.ServerStatsCollector.RecordDisconnection + nameWithType: ServerStatsCollector.RecordDisconnection +- uid: EchoHub.Server.Services.Stats.ServerStatsCollector.RecordKick + name: RecordKick() + href: api/server/EchoHub.Server.Services.Stats.ServerStatsCollector.html#EchoHub_Server_Services_Stats_ServerStatsCollector_RecordKick + commentId: M:EchoHub.Server.Services.Stats.ServerStatsCollector.RecordKick + fullName: EchoHub.Server.Services.Stats.ServerStatsCollector.RecordKick() + nameWithType: ServerStatsCollector.RecordKick() +- uid: EchoHub.Server.Services.Stats.ServerStatsCollector.RecordKick* + name: RecordKick + href: api/server/EchoHub.Server.Services.Stats.ServerStatsCollector.html#EchoHub_Server_Services_Stats_ServerStatsCollector_RecordKick_ + commentId: Overload:EchoHub.Server.Services.Stats.ServerStatsCollector.RecordKick + fullName: EchoHub.Server.Services.Stats.ServerStatsCollector.RecordKick + nameWithType: ServerStatsCollector.RecordKick +- uid: EchoHub.Server.Services.Stats.ServerStatsCollector.RecordOnline(System.Int32) + name: RecordOnline(int) + href: api/server/EchoHub.Server.Services.Stats.ServerStatsCollector.html#EchoHub_Server_Services_Stats_ServerStatsCollector_RecordOnline_System_Int32_ + commentId: M:EchoHub.Server.Services.Stats.ServerStatsCollector.RecordOnline(System.Int32) + name.vb: RecordOnline(Integer) + fullName: EchoHub.Server.Services.Stats.ServerStatsCollector.RecordOnline(int) + fullName.vb: EchoHub.Server.Services.Stats.ServerStatsCollector.RecordOnline(Integer) + nameWithType: ServerStatsCollector.RecordOnline(int) + nameWithType.vb: ServerStatsCollector.RecordOnline(Integer) +- uid: EchoHub.Server.Services.Stats.ServerStatsCollector.RecordOnline* + name: RecordOnline + href: api/server/EchoHub.Server.Services.Stats.ServerStatsCollector.html#EchoHub_Server_Services_Stats_ServerStatsCollector_RecordOnline_ + commentId: Overload:EchoHub.Server.Services.Stats.ServerStatsCollector.RecordOnline + fullName: EchoHub.Server.Services.Stats.ServerStatsCollector.RecordOnline + nameWithType: ServerStatsCollector.RecordOnline +- uid: EchoHub.Server.Services.Stats.ServerStatsCollector.SnapshotAndReset(System.Int32) + name: SnapshotAndReset(int) + href: api/server/EchoHub.Server.Services.Stats.ServerStatsCollector.html#EchoHub_Server_Services_Stats_ServerStatsCollector_SnapshotAndReset_System_Int32_ + commentId: M:EchoHub.Server.Services.Stats.ServerStatsCollector.SnapshotAndReset(System.Int32) + name.vb: SnapshotAndReset(Integer) + fullName: EchoHub.Server.Services.Stats.ServerStatsCollector.SnapshotAndReset(int) + fullName.vb: EchoHub.Server.Services.Stats.ServerStatsCollector.SnapshotAndReset(Integer) + nameWithType: ServerStatsCollector.SnapshotAndReset(int) + nameWithType.vb: ServerStatsCollector.SnapshotAndReset(Integer) +- uid: EchoHub.Server.Services.Stats.ServerStatsCollector.SnapshotAndReset* + name: SnapshotAndReset + href: api/server/EchoHub.Server.Services.Stats.ServerStatsCollector.html#EchoHub_Server_Services_Stats_ServerStatsCollector_SnapshotAndReset_ + commentId: Overload:EchoHub.Server.Services.Stats.ServerStatsCollector.SnapshotAndReset + fullName: EchoHub.Server.Services.Stats.ServerStatsCollector.SnapshotAndReset + nameWithType: ServerStatsCollector.SnapshotAndReset +- uid: EchoHub.Server.Services.Stats.ServerStatsReportService + name: ServerStatsReportService + href: api/server/EchoHub.Server.Services.Stats.ServerStatsReportService.html + commentId: T:EchoHub.Server.Services.Stats.ServerStatsReportService + fullName: EchoHub.Server.Services.Stats.ServerStatsReportService + nameWithType: ServerStatsReportService +- uid: EchoHub.Server.Services.Stats.ServerStatsReportService.#ctor(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory,EchoHub.Server.Services.PresenceTracker,EchoHub.Server.Services.Stats.ServerStatsCollector,EchoHub.Server.Config.StatsOptions,Microsoft.Extensions.Logging.ILogger{EchoHub.Server.Services.Stats.ServerStatsReportService}) + name: ServerStatsReportService(IServiceScopeFactory, PresenceTracker, ServerStatsCollector, StatsOptions, ILogger) + href: api/server/EchoHub.Server.Services.Stats.ServerStatsReportService.html#EchoHub_Server_Services_Stats_ServerStatsReportService__ctor_Microsoft_Extensions_DependencyInjection_IServiceScopeFactory_EchoHub_Server_Services_PresenceTracker_EchoHub_Server_Services_Stats_ServerStatsCollector_EchoHub_Server_Config_StatsOptions_Microsoft_Extensions_Logging_ILogger_EchoHub_Server_Services_Stats_ServerStatsReportService__ + commentId: M:EchoHub.Server.Services.Stats.ServerStatsReportService.#ctor(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory,EchoHub.Server.Services.PresenceTracker,EchoHub.Server.Services.Stats.ServerStatsCollector,EchoHub.Server.Config.StatsOptions,Microsoft.Extensions.Logging.ILogger{EchoHub.Server.Services.Stats.ServerStatsReportService}) + name.vb: New(IServiceScopeFactory, PresenceTracker, ServerStatsCollector, StatsOptions, ILogger(Of ServerStatsReportService)) + fullName: EchoHub.Server.Services.Stats.ServerStatsReportService.ServerStatsReportService(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory, EchoHub.Server.Services.PresenceTracker, EchoHub.Server.Services.Stats.ServerStatsCollector, EchoHub.Server.Config.StatsOptions, Microsoft.Extensions.Logging.ILogger) + fullName.vb: EchoHub.Server.Services.Stats.ServerStatsReportService.New(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory, EchoHub.Server.Services.PresenceTracker, EchoHub.Server.Services.Stats.ServerStatsCollector, EchoHub.Server.Config.StatsOptions, Microsoft.Extensions.Logging.ILogger(Of EchoHub.Server.Services.Stats.ServerStatsReportService)) + nameWithType: ServerStatsReportService.ServerStatsReportService(IServiceScopeFactory, PresenceTracker, ServerStatsCollector, StatsOptions, ILogger) + nameWithType.vb: ServerStatsReportService.New(IServiceScopeFactory, PresenceTracker, ServerStatsCollector, StatsOptions, ILogger(Of ServerStatsReportService)) +- uid: EchoHub.Server.Services.Stats.ServerStatsReportService.#ctor* + name: ServerStatsReportService + href: api/server/EchoHub.Server.Services.Stats.ServerStatsReportService.html#EchoHub_Server_Services_Stats_ServerStatsReportService__ctor_ + commentId: Overload:EchoHub.Server.Services.Stats.ServerStatsReportService.#ctor + name.vb: New + fullName: EchoHub.Server.Services.Stats.ServerStatsReportService.ServerStatsReportService + fullName.vb: EchoHub.Server.Services.Stats.ServerStatsReportService.New + nameWithType: ServerStatsReportService.ServerStatsReportService + nameWithType.vb: ServerStatsReportService.New +- uid: EchoHub.Server.Services.Stats.ServerStatsReportService.ExecuteAsync(System.Threading.CancellationToken) + name: ExecuteAsync(CancellationToken) + href: api/server/EchoHub.Server.Services.Stats.ServerStatsReportService.html#EchoHub_Server_Services_Stats_ServerStatsReportService_ExecuteAsync_System_Threading_CancellationToken_ + commentId: M:EchoHub.Server.Services.Stats.ServerStatsReportService.ExecuteAsync(System.Threading.CancellationToken) + fullName: EchoHub.Server.Services.Stats.ServerStatsReportService.ExecuteAsync(System.Threading.CancellationToken) + nameWithType: ServerStatsReportService.ExecuteAsync(CancellationToken) +- uid: EchoHub.Server.Services.Stats.ServerStatsReportService.ExecuteAsync* + name: ExecuteAsync + href: api/server/EchoHub.Server.Services.Stats.ServerStatsReportService.html#EchoHub_Server_Services_Stats_ServerStatsReportService_ExecuteAsync_ + commentId: Overload:EchoHub.Server.Services.Stats.ServerStatsReportService.ExecuteAsync + fullName: EchoHub.Server.Services.Stats.ServerStatsReportService.ExecuteAsync + nameWithType: ServerStatsReportService.ExecuteAsync +- uid: EchoHub.Server.Services.Stats.StatsCounters + name: StatsCounters + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html + commentId: T:EchoHub.Server.Services.Stats.StatsCounters + fullName: EchoHub.Server.Services.Stats.StatsCounters + nameWithType: StatsCounters +- uid: EchoHub.Server.Services.Stats.StatsCounters.#ctor(System.Int64,System.Int64,System.Int64,System.Int64,System.Int32) + name: StatsCounters(long, long, long, long, int) + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html#EchoHub_Server_Services_Stats_StatsCounters__ctor_System_Int64_System_Int64_System_Int64_System_Int64_System_Int32_ + commentId: M:EchoHub.Server.Services.Stats.StatsCounters.#ctor(System.Int64,System.Int64,System.Int64,System.Int64,System.Int32) + name.vb: New(Long, Long, Long, Long, Integer) + fullName: EchoHub.Server.Services.Stats.StatsCounters.StatsCounters(long, long, long, long, int) + fullName.vb: EchoHub.Server.Services.Stats.StatsCounters.New(Long, Long, Long, Long, Integer) + nameWithType: StatsCounters.StatsCounters(long, long, long, long, int) + nameWithType.vb: StatsCounters.New(Long, Long, Long, Long, Integer) +- uid: EchoHub.Server.Services.Stats.StatsCounters.#ctor* + name: StatsCounters + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html#EchoHub_Server_Services_Stats_StatsCounters__ctor_ + commentId: Overload:EchoHub.Server.Services.Stats.StatsCounters.#ctor + name.vb: New + fullName: EchoHub.Server.Services.Stats.StatsCounters.StatsCounters + fullName.vb: EchoHub.Server.Services.Stats.StatsCounters.New + nameWithType: StatsCounters.StatsCounters + nameWithType.vb: StatsCounters.New +- uid: EchoHub.Server.Services.Stats.StatsCounters.Bans + name: Bans + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html#EchoHub_Server_Services_Stats_StatsCounters_Bans + commentId: P:EchoHub.Server.Services.Stats.StatsCounters.Bans + fullName: EchoHub.Server.Services.Stats.StatsCounters.Bans + nameWithType: StatsCounters.Bans +- uid: EchoHub.Server.Services.Stats.StatsCounters.Bans* + name: Bans + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html#EchoHub_Server_Services_Stats_StatsCounters_Bans_ + commentId: Overload:EchoHub.Server.Services.Stats.StatsCounters.Bans + fullName: EchoHub.Server.Services.Stats.StatsCounters.Bans + nameWithType: StatsCounters.Bans +- uid: EchoHub.Server.Services.Stats.StatsCounters.Connections + name: Connections + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html#EchoHub_Server_Services_Stats_StatsCounters_Connections + commentId: P:EchoHub.Server.Services.Stats.StatsCounters.Connections + fullName: EchoHub.Server.Services.Stats.StatsCounters.Connections + nameWithType: StatsCounters.Connections +- uid: EchoHub.Server.Services.Stats.StatsCounters.Connections* + name: Connections + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html#EchoHub_Server_Services_Stats_StatsCounters_Connections_ + commentId: Overload:EchoHub.Server.Services.Stats.StatsCounters.Connections + fullName: EchoHub.Server.Services.Stats.StatsCounters.Connections + nameWithType: StatsCounters.Connections +- uid: EchoHub.Server.Services.Stats.StatsCounters.Deconstruct(System.Int64@,System.Int64@,System.Int64@,System.Int64@,System.Int32@) + name: Deconstruct(out long, out long, out long, out long, out int) + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html#EchoHub_Server_Services_Stats_StatsCounters_Deconstruct_System_Int64__System_Int64__System_Int64__System_Int64__System_Int32__ + commentId: M:EchoHub.Server.Services.Stats.StatsCounters.Deconstruct(System.Int64@,System.Int64@,System.Int64@,System.Int64@,System.Int32@) + name.vb: Deconstruct(Long, Long, Long, Long, Integer) + fullName: EchoHub.Server.Services.Stats.StatsCounters.Deconstruct(out long, out long, out long, out long, out int) + fullName.vb: EchoHub.Server.Services.Stats.StatsCounters.Deconstruct(Long, Long, Long, Long, Integer) + nameWithType: StatsCounters.Deconstruct(out long, out long, out long, out long, out int) + nameWithType.vb: StatsCounters.Deconstruct(Long, Long, Long, Long, Integer) +- uid: EchoHub.Server.Services.Stats.StatsCounters.Deconstruct* + name: Deconstruct + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html#EchoHub_Server_Services_Stats_StatsCounters_Deconstruct_ + commentId: Overload:EchoHub.Server.Services.Stats.StatsCounters.Deconstruct + fullName: EchoHub.Server.Services.Stats.StatsCounters.Deconstruct + nameWithType: StatsCounters.Deconstruct +- uid: EchoHub.Server.Services.Stats.StatsCounters.Disconnections + name: Disconnections + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html#EchoHub_Server_Services_Stats_StatsCounters_Disconnections + commentId: P:EchoHub.Server.Services.Stats.StatsCounters.Disconnections + fullName: EchoHub.Server.Services.Stats.StatsCounters.Disconnections + nameWithType: StatsCounters.Disconnections +- uid: EchoHub.Server.Services.Stats.StatsCounters.Disconnections* + name: Disconnections + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html#EchoHub_Server_Services_Stats_StatsCounters_Disconnections_ + commentId: Overload:EchoHub.Server.Services.Stats.StatsCounters.Disconnections + fullName: EchoHub.Server.Services.Stats.StatsCounters.Disconnections + nameWithType: StatsCounters.Disconnections +- uid: EchoHub.Server.Services.Stats.StatsCounters.Equals(EchoHub.Server.Services.Stats.StatsCounters) + name: Equals(StatsCounters) + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html#EchoHub_Server_Services_Stats_StatsCounters_Equals_EchoHub_Server_Services_Stats_StatsCounters_ + commentId: M:EchoHub.Server.Services.Stats.StatsCounters.Equals(EchoHub.Server.Services.Stats.StatsCounters) + fullName: EchoHub.Server.Services.Stats.StatsCounters.Equals(EchoHub.Server.Services.Stats.StatsCounters) + nameWithType: StatsCounters.Equals(StatsCounters) +- uid: EchoHub.Server.Services.Stats.StatsCounters.Equals(System.Object) + name: Equals(object) + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html#EchoHub_Server_Services_Stats_StatsCounters_Equals_System_Object_ + commentId: M:EchoHub.Server.Services.Stats.StatsCounters.Equals(System.Object) + name.vb: Equals(Object) + fullName: EchoHub.Server.Services.Stats.StatsCounters.Equals(object) + fullName.vb: EchoHub.Server.Services.Stats.StatsCounters.Equals(Object) + nameWithType: StatsCounters.Equals(object) + nameWithType.vb: StatsCounters.Equals(Object) +- uid: EchoHub.Server.Services.Stats.StatsCounters.Equals* + name: Equals + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html#EchoHub_Server_Services_Stats_StatsCounters_Equals_ + commentId: Overload:EchoHub.Server.Services.Stats.StatsCounters.Equals + fullName: EchoHub.Server.Services.Stats.StatsCounters.Equals + nameWithType: StatsCounters.Equals +- uid: EchoHub.Server.Services.Stats.StatsCounters.GetHashCode + name: GetHashCode() + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html#EchoHub_Server_Services_Stats_StatsCounters_GetHashCode + commentId: M:EchoHub.Server.Services.Stats.StatsCounters.GetHashCode + fullName: EchoHub.Server.Services.Stats.StatsCounters.GetHashCode() + nameWithType: StatsCounters.GetHashCode() +- uid: EchoHub.Server.Services.Stats.StatsCounters.GetHashCode* + name: GetHashCode + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html#EchoHub_Server_Services_Stats_StatsCounters_GetHashCode_ + commentId: Overload:EchoHub.Server.Services.Stats.StatsCounters.GetHashCode + fullName: EchoHub.Server.Services.Stats.StatsCounters.GetHashCode + nameWithType: StatsCounters.GetHashCode +- uid: EchoHub.Server.Services.Stats.StatsCounters.Kicks + name: Kicks + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html#EchoHub_Server_Services_Stats_StatsCounters_Kicks + commentId: P:EchoHub.Server.Services.Stats.StatsCounters.Kicks + fullName: EchoHub.Server.Services.Stats.StatsCounters.Kicks + nameWithType: StatsCounters.Kicks +- uid: EchoHub.Server.Services.Stats.StatsCounters.Kicks* + name: Kicks + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html#EchoHub_Server_Services_Stats_StatsCounters_Kicks_ + commentId: Overload:EchoHub.Server.Services.Stats.StatsCounters.Kicks + fullName: EchoHub.Server.Services.Stats.StatsCounters.Kicks + nameWithType: StatsCounters.Kicks +- uid: EchoHub.Server.Services.Stats.StatsCounters.PeakOnline + name: PeakOnline + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html#EchoHub_Server_Services_Stats_StatsCounters_PeakOnline + commentId: P:EchoHub.Server.Services.Stats.StatsCounters.PeakOnline + fullName: EchoHub.Server.Services.Stats.StatsCounters.PeakOnline + nameWithType: StatsCounters.PeakOnline +- uid: EchoHub.Server.Services.Stats.StatsCounters.PeakOnline* + name: PeakOnline + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html#EchoHub_Server_Services_Stats_StatsCounters_PeakOnline_ + commentId: Overload:EchoHub.Server.Services.Stats.StatsCounters.PeakOnline + fullName: EchoHub.Server.Services.Stats.StatsCounters.PeakOnline + nameWithType: StatsCounters.PeakOnline +- uid: EchoHub.Server.Services.Stats.StatsCounters.ToString + name: ToString() + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html#EchoHub_Server_Services_Stats_StatsCounters_ToString + commentId: M:EchoHub.Server.Services.Stats.StatsCounters.ToString + fullName: EchoHub.Server.Services.Stats.StatsCounters.ToString() + nameWithType: StatsCounters.ToString() +- uid: EchoHub.Server.Services.Stats.StatsCounters.ToString* + name: ToString + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html#EchoHub_Server_Services_Stats_StatsCounters_ToString_ + commentId: Overload:EchoHub.Server.Services.Stats.StatsCounters.ToString + fullName: EchoHub.Server.Services.Stats.StatsCounters.ToString + nameWithType: StatsCounters.ToString +- uid: EchoHub.Server.Services.Stats.StatsCounters.op_Equality(EchoHub.Server.Services.Stats.StatsCounters,EchoHub.Server.Services.Stats.StatsCounters) + name: operator ==(StatsCounters, StatsCounters) + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html#EchoHub_Server_Services_Stats_StatsCounters_op_Equality_EchoHub_Server_Services_Stats_StatsCounters_EchoHub_Server_Services_Stats_StatsCounters_ + commentId: M:EchoHub.Server.Services.Stats.StatsCounters.op_Equality(EchoHub.Server.Services.Stats.StatsCounters,EchoHub.Server.Services.Stats.StatsCounters) + name.vb: =(StatsCounters, StatsCounters) + fullName: EchoHub.Server.Services.Stats.StatsCounters.operator ==(EchoHub.Server.Services.Stats.StatsCounters, EchoHub.Server.Services.Stats.StatsCounters) + fullName.vb: EchoHub.Server.Services.Stats.StatsCounters.=(EchoHub.Server.Services.Stats.StatsCounters, EchoHub.Server.Services.Stats.StatsCounters) + nameWithType: StatsCounters.operator ==(StatsCounters, StatsCounters) + nameWithType.vb: StatsCounters.=(StatsCounters, StatsCounters) +- uid: EchoHub.Server.Services.Stats.StatsCounters.op_Equality* + name: operator == + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html#EchoHub_Server_Services_Stats_StatsCounters_op_Equality_ + commentId: Overload:EchoHub.Server.Services.Stats.StatsCounters.op_Equality + name.vb: = + fullName: EchoHub.Server.Services.Stats.StatsCounters.operator == + fullName.vb: EchoHub.Server.Services.Stats.StatsCounters.= + nameWithType: StatsCounters.operator == + nameWithType.vb: StatsCounters.= +- uid: EchoHub.Server.Services.Stats.StatsCounters.op_Inequality(EchoHub.Server.Services.Stats.StatsCounters,EchoHub.Server.Services.Stats.StatsCounters) + name: operator !=(StatsCounters, StatsCounters) + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html#EchoHub_Server_Services_Stats_StatsCounters_op_Inequality_EchoHub_Server_Services_Stats_StatsCounters_EchoHub_Server_Services_Stats_StatsCounters_ + commentId: M:EchoHub.Server.Services.Stats.StatsCounters.op_Inequality(EchoHub.Server.Services.Stats.StatsCounters,EchoHub.Server.Services.Stats.StatsCounters) + name.vb: <>(StatsCounters, StatsCounters) + fullName: EchoHub.Server.Services.Stats.StatsCounters.operator !=(EchoHub.Server.Services.Stats.StatsCounters, EchoHub.Server.Services.Stats.StatsCounters) + fullName.vb: EchoHub.Server.Services.Stats.StatsCounters.<>(EchoHub.Server.Services.Stats.StatsCounters, EchoHub.Server.Services.Stats.StatsCounters) + nameWithType: StatsCounters.operator !=(StatsCounters, StatsCounters) + nameWithType.vb: StatsCounters.<>(StatsCounters, StatsCounters) +- uid: EchoHub.Server.Services.Stats.StatsCounters.op_Inequality* + name: operator != + href: api/server/EchoHub.Server.Services.Stats.StatsCounters.html#EchoHub_Server_Services_Stats_StatsCounters_op_Inequality_ + commentId: Overload:EchoHub.Server.Services.Stats.StatsCounters.op_Inequality + name.vb: <> + fullName: EchoHub.Server.Services.Stats.StatsCounters.operator != + fullName.vb: EchoHub.Server.Services.Stats.StatsCounters.<> + nameWithType: StatsCounters.operator != + nameWithType.vb: StatsCounters.<> - uid: EchoHub.Server.Services.UserService name: UserService href: api/server/EchoHub.Server.Services.UserService.html