diff --git a/.github/workflows/ci-suite.yml b/.github/workflows/ci-suite.yml
index ffdca312c0..64ca278308 100644
--- a/.github/workflows/ci-suite.yml
+++ b/.github/workflows/ci-suite.yml
@@ -187,9 +187,7 @@ jobs:
env:
TGS_TEST_DATABASE_TYPE: SqlServer
TGS_TEST_DUMP_API_SPEC: yes
- concurrency: integration-windows-${{ github.head_ref }}
strategy:
- max-parallel: 2
matrix:
watchdog-type: [ 'Basic', 'System' ]
configuration: [ 'Debug', 'Release' ]
@@ -303,9 +301,7 @@ jobs:
--health-interval=10s
--health-timeout=5s
--health-retries=3
- concurrency: integration-linux-${{ github.head_ref }}
strategy:
- max-parallel: 2
matrix:
database-type: [ 'Sqlite', 'PostgresSql', 'MariaDB', 'MySql' ]
watchdog-type: [ 'System' ]
@@ -773,7 +769,7 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install -y xmlstarlet
- xmlstarlet sel -N X="http://schemas.microsoft.com/developer/msbuild/2003" --template --value-of /X:Project/X:PropertyGroup/X:TgsCoreVersion build/Version.props >> $Env:GITHUB_ENV
+ echo "TGS_VERSION=$(xmlstarlet sel -N X="http://schemas.microsoft.com/developer/msbuild/2003" --template --value-of /X:Project/X:PropertyGroup/X:TgsCoreVersion build/Version.props)" >> $Env:GITHUB_ENV
- name: Docker Build and Push
uses: elgohr/Publish-Docker-Github-Action@master
diff --git a/build/Version.props b/build/Version.props
index 1609c6d1e7..8d2a18c79a 100644
--- a/build/Version.props
+++ b/build/Version.props
@@ -3,7 +3,7 @@
- 4.15.3
+ 4.15.4
4.0.0
9.3.0
9.3.1
diff --git a/src/Tgstation.Server.Host/Components/Chat/ChatManager.cs b/src/Tgstation.Server.Host/Components/Chat/ChatManager.cs
index b5f105ea3e..3aaf187d80 100644
--- a/src/Tgstation.Server.Host/Components/Chat/ChatManager.cs
+++ b/src/Tgstation.Server.Host/Components/Chat/ChatManager.cs
@@ -190,9 +190,16 @@ namespace Tgstation.Server.Host.Components.Chat
throw new ArgumentNullException(nameof(newChannels));
logger.LogTrace("ChangeChannels {0}...", connectionId);
- var provider = await RemoveProvider(connectionId, false, cancellationToken).ConfigureAwait(false);
+ var provider = await RemoveProviderChannels(connectionId, false, cancellationToken).ConfigureAwait(false);
if (provider == null)
return;
+
+ if (!provider.Connected)
+ {
+ logger.LogDebug("Cannot map channels, provider {providerId} disconnected!", connectionId);
+ return;
+ }
+
var results = await provider.MapChannels(newChannels, cancellationToken).ConfigureAwait(false);
lock (activeChatBots)
{
@@ -260,29 +267,14 @@ namespace Tgstation.Server.Host.Components.Chat
throw new ArgumentNullException(nameof(newSettings));
logger.LogTrace("ChangeSettings...");
- IProvider provider;
-
- async Task DisconnectProvider(IProvider p)
- {
- try
- {
- await p.Disconnect(cancellationToken).ConfigureAwait(false);
- }
- finally
- {
- await p.DisposeAsync().ConfigureAwait(false);
- }
- }
Task disconnectTask;
+ IProvider provider = null;
lock (providers)
{
// raw settings changes forces a rebuild of the provider
- if (providers.TryGetValue(newSettings.Id.Value, out provider))
- {
- providers.Remove(newSettings.Id.Value);
- disconnectTask = DisconnectProvider(provider);
- }
+ if (providers.ContainsKey(newSettings.Id.Value))
+ disconnectTask = DeleteConnection(newSettings.Id.Value, cancellationToken);
else
disconnectTask = Task.CompletedTask;
if (newSettings.Enabled.Value)
@@ -430,7 +422,6 @@ namespace Tgstation.Server.Host.Components.Chat
builtinCommands.Add(tgsCommand.Name.ToUpperInvariant(), tgsCommand);
var initialChatBots = activeChatBots.ToList();
await Task.WhenAll(initialChatBots.Select(x => ChangeSettings(x, cancellationToken))).ConfigureAwait(false);
- await Task.WhenAll(initialChatBots.Select(x => ChangeChannels(x.Id.Value, x.Channels, cancellationToken))).ConfigureAwait(false);
initialProviderConnectionsTask = InitialConnection();
chatHandler = MonitorMessages(handlerCts.Token);
}
@@ -441,7 +432,7 @@ namespace Tgstation.Server.Host.Components.Chat
handlerCts.Cancel();
if (chatHandler != null)
await chatHandler.ConfigureAwait(false);
- await Task.WhenAll(providers.Select(x => x.Value).Select(x => x.Disconnect(cancellationToken))).ConfigureAwait(false);
+ await Task.WhenAll(providers.Select(x => x.Key).Select(x => DeleteConnection(x, cancellationToken))).ConfigureAwait(false);
await messageSendTask.ConfigureAwait(false);
}
@@ -480,7 +471,7 @@ namespace Tgstation.Server.Host.Components.Chat
///
public async Task DeleteConnection(long connectionId, CancellationToken cancellationToken)
{
- var provider = await RemoveProvider(connectionId, true, cancellationToken).ConfigureAwait(false);
+ var provider = await RemoveProviderChannels(connectionId, true, cancellationToken).ConfigureAwait(false);
if (provider != null)
try
{
@@ -510,23 +501,28 @@ namespace Tgstation.Server.Host.Components.Chat
}
///
- /// Remove a from and optionally updating the as well.
+ /// Remove a from optionally removing the provider itself from and updating the as well.
///
/// The of the to delete.
- /// If should be update.
+ /// If the provider should be removed from and 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)
+ async Task RemoveProviderChannels(long connectionId, bool removeProvider, CancellationToken cancellationToken)
{
- logger.LogTrace("RemoveProvider {0}...", connectionId);
+ logger.LogTrace("RemoveProviderChannels {0}...", connectionId);
IProvider provider;
lock (providers)
+ {
if (!providers.TryGetValue(connectionId, out provider))
{
logger.LogTrace("Aborted, no such provider!");
return null;
}
+ if (removeProvider)
+ providers.Remove(connectionId);
+ }
+
Task trackingContextsUpdateTask;
lock (mappedChannels)
{
@@ -535,7 +531,7 @@ namespace Tgstation.Server.Host.Components.Chat
var newMappedChannels = mappedChannels.Select(y => y.Value.Channel).ToList();
- if (updateTrackings)
+ if (removeProvider)
lock (trackingContexts)
trackingContextsUpdateTask = Task.WhenAll(trackingContexts.Select(x => x.UpdateChannels(newMappedChannels, cancellationToken)));
else
@@ -607,6 +603,7 @@ namespace Tgstation.Server.Host.Components.Chat
.First();
mappedChannel = mappedChannels
.Where(x => x.Value.ProviderId == providerId && x.Value.ProviderChannelId == providerChannelId)
+ .Select(x => (KeyValuePair?)x)
.FirstOrDefault();
}
@@ -652,12 +649,11 @@ namespace Tgstation.Server.Host.Components.Chat
return;
}
- var mappingNonNullableKvp = mappedChannel.Value;
- var mapping = mappingNonNullableKvp.Value;
+ var mappingChannelRepresentation = mappedChannel.Value.Value.Channel;
- message.User.Channel.Id = mapping.Channel.Id;
- message.User.Channel.Tag = mapping.Channel.Tag;
- message.User.Channel.IsAdminChannel = mapping.Channel.IsAdminChannel;
+ message.User.Channel.Id = mappingChannelRepresentation.Id;
+ message.User.Channel.Tag = mappingChannelRepresentation.Tag;
+ message.User.Channel.IsAdminChannel = mappingChannelRepresentation.IsAdminChannel;
}
var splits = new List(message.Content.Trim().Split(' '));
diff --git a/src/Tgstation.Server.Host/Components/Chat/Providers/DiscordProvider.cs b/src/Tgstation.Server.Host/Components/Chat/Providers/DiscordProvider.cs
index cc6942b1d2..88755dc418 100644
--- a/src/Tgstation.Server.Host/Components/Chat/Providers/DiscordProvider.cs
+++ b/src/Tgstation.Server.Host/Components/Chat/Providers/DiscordProvider.cs
@@ -93,6 +93,11 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
///
Snowflake currentUserId;
+ ///
+ /// The bot's username at the time of connection.
+ ///
+ string initialUserName;
+
///
/// Normalize a discord mention string.
///
@@ -194,20 +199,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
if (channels == null)
throw new ArgumentNullException(nameof(channels));
- if (!Connected)
- {
- Logger.LogWarning("Cannot map channels, provider disconnected!");
- return Array.Empty();
- }
-
- var usersClient = serviceProvider.GetRequiredService();
- var currentUserResponse = await usersClient.GetCurrentUserAsync(cancellationToken).ConfigureAwait(false);
-
- if (!currentUserResponse.IsSuccess)
- {
- Logger.LogWarning("Error retrieving current Discord user: {0}", currentUserResponse.Error.Message);
- return Array.Empty();
- }
+ bool remapRequired = false;
async Task GetModelChannelFromDBChannel(Api.Models.ChatChannel channelFromDB)
{
@@ -215,14 +207,12 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
throw new InvalidOperationException("ChatChannel missing DiscordChannelId!");
var channelId = channelFromDB.DiscordChannelId.Value;
- ulong discordChannelId;
string connectionName;
string friendlyName;
if (channelId == 0)
{
- connectionName = currentUserResponse.Entity.Username;
+ connectionName = initialUserName;
friendlyName = "(Unmapped accessible channels)";
- discordChannelId = 0;
}
else
{
@@ -231,6 +221,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
if (!discordChannelResponse.IsSuccess)
{
Logger.LogWarning("Error retrieving discord channel {0}: {1}", channelId, discordChannelResponse.Error.Message);
+ remapRequired = true;
return null;
}
@@ -240,7 +231,6 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
return null;
}
- discordChannelId = discordChannelResponse.Entity.ID.Value;
friendlyName = discordChannelResponse.Entity.Name.Value;
var guildsClient = serviceProvider.GetRequiredService();
@@ -254,6 +244,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
"Error retrieving discord guild {0}: {1}",
discordChannelResponse.Entity.GuildID.Value,
discordChannelResponse.Error.Message);
+ remapRequired = true;
return null;
}
@@ -262,7 +253,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
var channelModel = new ChannelRepresentation
{
- RealId = discordChannelId,
+ RealId = channelId,
IsAdminChannel = channelFromDB.IsAdminChannel == true,
ConnectionName = connectionName,
FriendlyName = friendlyName,
@@ -276,13 +267,13 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
var tasks = channels
.Select(x => GetModelChannelFromDBChannel(x))
- .Where(x => x != null)
.ToList();
await Task.WhenAll(tasks);
var enumerator = tasks
.Select(x => x.Result)
+ .Where(x => x != null)
.ToList();
lock (mappedChannels)
@@ -291,6 +282,9 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
mappedChannels.AddRange(enumerator.Select(x => x.RealId));
}
+ if (remapRequired)
+ EnqueueMessage(null);
+
return enumerator;
}
@@ -613,6 +607,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
gatewayReadyTcs = new TaskCompletionSource