From 9bbe7135f0517b801fefa8a76680bfe67fa5b5c5 Mon Sep 17 00:00:00 2001 From: Cyberboss Date: Mon, 16 Jul 2018 15:52:12 -0400 Subject: [PATCH] Get things building again --- src/DMAPI/tgs.dm | 3 +- .../Models/ChatChannel.cs | 2 +- .../Components/Chat/Channel.cs | 13 ++-- .../Components/Chat/Chat.cs | 67 ++++++++++++++----- .../Components/Chat/Commands/Command.cs | 18 +++++ .../Components/Chat/Commands/CustomCommand.cs | 10 +++ .../Components/Chat/IChat.cs | 8 +++ .../Components/Chat/IJsonTrackingContext.cs | 12 ++++ .../Components/Chat/Providers/IProvider.cs | 7 ++ .../Components/Chat/User.cs | 5 +- 10 files changed, 121 insertions(+), 24 deletions(-) diff --git a/src/DMAPI/tgs.dm b/src/DMAPI/tgs.dm index 4e9749084b..c3daf1a380 100644 --- a/src/DMAPI/tgs.dm +++ b/src/DMAPI/tgs.dm @@ -97,8 +97,7 @@ /datum/tgs_chat_channel var/id //internal channel representation var/friendly_name //user friendly channel name - var/server_name //server name the channel resides on - var/provider_name //chat provider for the channel + var/connection_name //the name of the configured chat connection var/is_admin_channel //if the server operator has marked this channel for game admins only var/is_private_channel //if this is a private chat channel diff --git a/src/Tgstation.Server.Api/Models/ChatChannel.cs b/src/Tgstation.Server.Api/Models/ChatChannel.cs index c7ab3b9b32..942154e506 100644 --- a/src/Tgstation.Server.Api/Models/ChatChannel.cs +++ b/src/Tgstation.Server.Api/Models/ChatChannel.cs @@ -13,7 +13,7 @@ /// /// The Discord channel ID /// - public long DiscordChannelId { get; set; } + public long? DiscordChannelId { get; set; } /// /// If the is an admin channel diff --git a/src/Tgstation.Server.Host/Components/Chat/Channel.cs b/src/Tgstation.Server.Host/Components/Chat/Channel.cs index 8a6cfc1d66..c2eab84dd8 100644 --- a/src/Tgstation.Server.Host/Components/Chat/Channel.cs +++ b/src/Tgstation.Server.Host/Components/Chat/Channel.cs @@ -17,13 +17,18 @@ public string FriendlyName { get; set; } /// - /// If this is considered a channel for admin commands + /// The name of the connection the belongs to /// - public bool IsAdminChannel { get; set; } + public string ConnectionName { get; set; } /// - /// If this i + /// If this is considered a channel for admin commands /// - public bool IsPrivateChannel { get; set; } + public bool IsAdmin { get; set; } + + /// + /// If this is a 1-to-1 chat channel + /// + public bool IsPrivate { get; set; } } } diff --git a/src/Tgstation.Server.Host/Components/Chat/Chat.cs b/src/Tgstation.Server.Host/Components/Chat/Chat.cs index 9f3e8e4324..862096ae44 100644 --- a/src/Tgstation.Server.Host/Components/Chat/Chat.cs +++ b/src/Tgstation.Server.Host/Components/Chat/Chat.cs @@ -1,8 +1,6 @@ -using Newtonsoft.Json; -using System; +using System; using System.Collections.Generic; using System.Linq; -using System.Reflection; using System.Threading; using System.Threading.Tasks; using Tgstation.Server.Api.Models.Internal; @@ -40,6 +38,9 @@ namespace Tgstation.Server.Host.Components.Chat /// readonly Dictionary mappedChannels; + /// + /// The active s for the + /// readonly List trackingContexts; /// @@ -52,6 +53,11 @@ namespace Tgstation.Server.Host.Components.Chat /// long channelIdCounter; + /// + /// If has been called + /// + bool started; + /// /// Construct a /// @@ -77,21 +83,43 @@ namespace Tgstation.Server.Host.Components.Chat I.Value.Dispose(); } + /// + /// Remove a from and optionally updating the as well + /// + /// The of the to delete + /// If should be update + /// The for the operation + /// A resulting in the being removed if it exists, otherwise + async Task RemoveProvider(long connectionId, bool updateTrackings, CancellationToken cancellationToken) + { + IProvider provider; + lock (providers) + if (!providers.TryGetValue(connectionId, out provider)) + return null; + Task task; + lock (mappedChannels) + { + foreach (var kvp in mappedChannels.Where(x => x.Value.ProviderId == connectionId)) + mappedChannels.Remove(kvp.Key); + + if (updateTrackings) + lock (trackingContexts) + task = Task.WhenAll(trackingContexts.Select(x => x.SetChannels(mappedChannels.Select(y => y.Value.Channel), cancellationToken))); + else + task = Task.CompletedTask; + } + await task.ConfigureAwait(false); + return provider; + } + /// public async Task ChangeChannels(long connectionId, IEnumerable newChannels, CancellationToken cancellationToken) { if (newChannels == null) throw new ArgumentNullException(nameof(newChannels)); - IProvider provider; - lock (providers) - if (!providers.TryGetValue(connectionId, out provider)) - return; - lock (mappedChannels) - foreach (var kvp in mappedChannels.Where(x => x.Value.ProviderId == connectionId)) - { - mappedChannels.Remove(kvp.Key); - - } + var provider = await RemoveProvider(connectionId, false, cancellationToken).ConfigureAwait(false); + if (provider == null) + return; var results = await provider.MapChannels(newChannels, cancellationToken).ConfigureAwait(false); if (results == null) //aborted return; @@ -152,7 +180,7 @@ namespace Tgstation.Server.Host.Components.Chat lock (mappedChannels) foreach (var channelId in mappedChannels.Where(x => x.Value.ProviderId == newSettings.Id).Select(x => x.Key)) mappedChannels.Remove(channelId); - if (newSettings.Enabled) + if (newSettings.Enabled && started) await provider.Connect(cancellationToken).ConfigureAwait(false); } @@ -188,10 +216,14 @@ namespace Tgstation.Server.Host.Components.Chat } /// - public Task StartAsync(CancellationToken cancellationToken) => Task.WhenAll(providers.Select(x => x.Value).Select(x => x.Connect(cancellationToken))); + public async Task StartAsync(CancellationToken cancellationToken) + { + await Task.WhenAll(providers.Select(x => x.Value).Select(x => x.Connect(cancellationToken))).ConfigureAwait(false); + started = true; + } /// - public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; + public Task StopAsync(CancellationToken cancellationToken) => Task.WhenAll(providers.Select(x => x.Value).Select(x => x.Disconnect(cancellationToken))); /// public async Task TrackJsons(string basePath, string channelsJsonName, string commandsJsonName, CancellationToken cancellationToken) @@ -229,5 +261,8 @@ namespace Tgstation.Server.Host.Components.Chat throw new InvalidOperationException("RegisterCommandHandler() already called!"); this.customCommandHandler = customCommandHandler ?? throw new ArgumentNullException(nameof(customCommandHandler)); } + + /// + public Task DeleteConnection(long connectionId, CancellationToken cancellationToken) => RemoveProvider(connectionId, true, cancellationToken); } } diff --git a/src/Tgstation.Server.Host/Components/Chat/Commands/Command.cs b/src/Tgstation.Server.Host/Components/Chat/Commands/Command.cs index 8ad981aee0..d5f192ec59 100644 --- a/src/Tgstation.Server.Host/Components/Chat/Commands/Command.cs +++ b/src/Tgstation.Server.Host/Components/Chat/Commands/Command.cs @@ -1,11 +1,29 @@ namespace Tgstation.Server.Host.Components.Chat.Commands { + /// + /// Represents a command that can be invoked by talking to chat bots + /// public abstract class Command { + /// + /// The text to invoke the command. May not be "?" or "help" (case-insensitive) + /// public string Name { get; set; } + + /// + /// The help text to display when queires are made about the command + /// public string HelpText { get; set; } + + /// + /// If the command should only be available to s who's has set + /// public bool AdminOnly { get; set; } + /// + /// Invoke the + /// + /// The text after with leading whitespace trimmed public abstract void Invoke(string arguments); } } diff --git a/src/Tgstation.Server.Host/Components/Chat/Commands/CustomCommand.cs b/src/Tgstation.Server.Host/Components/Chat/Commands/CustomCommand.cs index 94e8af328f..6221f531c1 100644 --- a/src/Tgstation.Server.Host/Components/Chat/Commands/CustomCommand.cs +++ b/src/Tgstation.Server.Host/Components/Chat/Commands/CustomCommand.cs @@ -2,10 +2,20 @@ namespace Tgstation.Server.Host.Components.Chat.Commands { + /// + /// Represents a command made from DM code + /// public sealed class CustomCommand : Command { + /// + /// The for the + /// ICustomCommandHandler handler; + /// + /// Set a new + /// + /// The value of public void SetHandler(ICustomCommandHandler handler) { if (this.handler != null) diff --git a/src/Tgstation.Server.Host/Components/Chat/IChat.cs b/src/Tgstation.Server.Host/Components/Chat/IChat.cs index a96d4b4fea..68c12aa1ed 100644 --- a/src/Tgstation.Server.Host/Components/Chat/IChat.cs +++ b/src/Tgstation.Server.Host/Components/Chat/IChat.cs @@ -33,6 +33,14 @@ namespace Tgstation.Server.Host.Components.Chat /// A representing the running operation. Will complete immediately if the property of is Task ChangeSettings(ChatSettings newSettings, CancellationToken cancellationToken); + /// + /// Disconnects and deletes a given connection + /// + /// The of the connection + /// The for the operation + /// A representing the running operation + Task DeleteConnection(long connectionId, CancellationToken cancellationToken); + /// /// Change chat channels /// diff --git a/src/Tgstation.Server.Host/Components/Chat/IJsonTrackingContext.cs b/src/Tgstation.Server.Host/Components/Chat/IJsonTrackingContext.cs index a4273ee79c..778b6d0d3c 100644 --- a/src/Tgstation.Server.Host/Components/Chat/IJsonTrackingContext.cs +++ b/src/Tgstation.Server.Host/Components/Chat/IJsonTrackingContext.cs @@ -11,7 +11,19 @@ namespace Tgstation.Server.Host.Components.Chat /// public interface IJsonTrackingContext : IDisposable { + /// + /// Read s from the + /// + /// The for the operation + /// A resulting in a of s in the Task> GetCustomCommands(CancellationToken cancellationToken); + + /// + /// Writes information about connected to the + /// + /// The s to write out + /// The for the operation + /// A representing the running operation Task SetChannels(IEnumerable channels, CancellationToken cancellationToken); } } \ No newline at end of file diff --git a/src/Tgstation.Server.Host/Components/Chat/Providers/IProvider.cs b/src/Tgstation.Server.Host/Components/Chat/Providers/IProvider.cs index 278ffa5813..7abe357269 100644 --- a/src/Tgstation.Server.Host/Components/Chat/Providers/IProvider.cs +++ b/src/Tgstation.Server.Host/Components/Chat/Providers/IProvider.cs @@ -32,6 +32,13 @@ namespace Tgstation.Server.Host.Components.Chat.Providers /// A resulting in on success, otherwise Task Connect(CancellationToken cancellationToken); + /// + /// Gracefully disconnects the provider. Implies a call to + /// + /// The for the operation + /// A representing the running operation + Task Disconnect(CancellationToken cancellationToken); + /// /// Get the s for given /// diff --git a/src/Tgstation.Server.Host/Components/Chat/User.cs b/src/Tgstation.Server.Host/Components/Chat/User.cs index 7b716dc419..12eff58285 100644 --- a/src/Tgstation.Server.Host/Components/Chat/User.cs +++ b/src/Tgstation.Server.Host/Components/Chat/User.cs @@ -1,10 +1,13 @@ namespace Tgstation.Server.Host.Components.Chat { + /// + /// + /// public sealed class User { long Id { get; set; } string FriendlyName { get; set; } string Mention { get; set; } - Channel channel { get; set; } + Channel Channel { get; set; } } }