Merge pull request #1426 from tgstation/1399-ChannelIdGeneric

Channel ID API change
This commit is contained in:
Jordan Dominion
2023-01-21 15:20:15 -05:00
committed by GitHub
18 changed files with 166 additions and 98 deletions
+4 -4
View File
@@ -3,11 +3,11 @@
<!-- Integration tests will ensure they match across the board -->
<Import Project="ControlPanelVersion.props" />
<PropertyGroup>
<TgsCoreVersion>5.2.4</TgsCoreVersion>
<TgsCoreVersion>5.3.0</TgsCoreVersion>
<TgsConfigVersion>4.4.0</TgsConfigVersion>
<TgsApiVersion>9.7.0</TgsApiVersion>
<TgsApiLibraryVersion>10.1.0</TgsApiLibraryVersion>
<TgsClientVersion>11.1.0</TgsClientVersion>
<TgsApiVersion>9.8.0</TgsApiVersion>
<TgsApiLibraryVersion>10.2.0</TgsApiLibraryVersion>
<TgsClientVersion>11.2.0</TgsClientVersion>
<TgsDmapiVersion>6.0.6</TgsDmapiVersion>
<TgsInteropVersion>5.3.0</TgsInteropVersion>
<TgsHostWatchdogVersion>1.2.0</TgsHostWatchdogVersion>
+16 -27
View File
@@ -1,49 +1,38 @@
using System.ComponentModel.DataAnnotations;
using System;
using System.ComponentModel.DataAnnotations;
using Tgstation.Server.Api.Models.Internal;
namespace Tgstation.Server.Api.Models
{
/// <summary>
/// Indicates a chat channel.
/// </summary>
public class ChatChannel
public class ChatChannel : ChatChannelBase
{
/// <summary>
/// The channel identifier. Supercedes <see cref="IrcChannel"/> and <see cref="DiscordChannelId"/>.
/// For <see cref="ChatProvider.Irc"/>, it's the IRC channel name and optional password colon separated.
/// For <see cref="ChatProvider.Discord"/>, it's the stringified Discord channel snowflake.
/// </summary>
[Required]
[StringLength(Limits.MaximumIndexableStringLength, MinimumLength = 1)]
public string? ChannelData { get; set; }
/// <summary>
/// The IRC channel name. Also potentially contains the channel passsword (if separated by a colon).
/// If multiple copies of the same channel with different keys are added to the server, the one that will be used is undefined.
/// </summary>
[ResponseOptions]
[StringLength(Limits.MaximumIndexableStringLength, MinimumLength = 1)]
[Obsolete($"Use {nameof(ChannelData)}")]
public string? IrcChannel { get; set; }
/// <summary>
/// The Discord channel ID.
/// </summary>
[Obsolete($"Use {nameof(ChannelData)}")]
[ResponseOptions]
public ulong? DiscordChannelId { get; set; }
/// <summary>
/// If the <see cref="ChatChannel"/> is an admin channel.
/// </summary>
[Required]
public bool? IsAdminChannel { get; set; }
/// <summary>
/// If the <see cref="ChatChannel"/> is a watchdog channel.
/// </summary>
[Required]
public bool? IsWatchdogChannel { get; set; }
/// <summary>
/// If the <see cref="ChatChannel"/> is an updates channel.
/// </summary>
[Required]
public bool? IsUpdatesChannel { get; set; }
/// <summary>
/// A custom tag users can define to group channels together.
/// </summary>
[ResponseOptions]
[StringLength(Limits.MaximumStringLength)]
public string? Tag { get; set; }
}
}
@@ -22,8 +22,8 @@ namespace Tgstation.Server.Api.Models.Internal
return true;
return Provider.Value switch
{
ChatProvider.Discord => Channels?.Select(x => x.DiscordChannelId.HasValue && x.IrcChannel == null).All(x => x) ?? true,
ChatProvider.Irc => Channels?.Select(x => !x.DiscordChannelId.HasValue && x.IrcChannel != null).All(x => x) ?? true,
ChatProvider.Discord => Channels?.Select(x => (x.DiscordChannelId.HasValue || ulong.TryParse(x.ChannelData, out _)) && x.IrcChannel == null).All(x => x) ?? true,
ChatProvider.Irc => Channels?.Select(x => !x.DiscordChannelId.HasValue && (x.IrcChannel != null || x.ChannelData != null)).All(x => x) ?? true,
_ => throw new InvalidOperationException("Invalid provider type!"),
};
}
@@ -0,0 +1,35 @@
using System.ComponentModel.DataAnnotations;
namespace Tgstation.Server.Api.Models.Internal
{
/// <summary>
/// Base chat channel class.
/// </summary>
public abstract class ChatChannelBase
{
/// <summary>
/// If the <see cref="ChatChannel"/> is an admin channel.
/// </summary>
[Required]
public bool? IsAdminChannel { get; set; }
/// <summary>
/// If the <see cref="ChatChannel"/> is a watchdog channel.
/// </summary>
[Required]
public bool? IsWatchdogChannel { get; set; }
/// <summary>
/// If the <see cref="ChatChannel"/> is an updates channel.
/// </summary>
[Required]
public bool? IsUpdatesChannel { get; set; }
/// <summary>
/// A custom tag users can define to group channels together.
/// </summary>
[ResponseOptions]
[StringLength(Limits.MaximumStringLength)]
public string? Tag { get; set; }
}
}
@@ -16,7 +16,7 @@
<RepositoryUrl>https://github.com/tgstation/tgstation-server</RepositoryUrl>
<Copyright>2018-2022</Copyright>
<PackageTags>json web api tgstation-server tgstation ss13 byond</PackageTags>
<PackageReleaseNotes>Retargeted to netstandard2.0 to support migrator.</PackageReleaseNotes>
<PackageReleaseNotes>Added ChannelData field to ChatChannels model.</PackageReleaseNotes>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<CodeAnalysisRuleSet>../../build/analyzers.ruleset</CodeAnalysisRuleSet>
@@ -16,7 +16,7 @@
<RepositoryUrl>https://github.com/tgstation/tgstation-server</RepositoryUrl>
<Copyright>2018-2022</Copyright>
<PackageTags>json web api tgstation-server tgstation ss13 byond client</PackageTags>
<PackageReleaseNotes>Retargeted to netstandard2.0 to support migrator. Fixed nullablity of IByondClient.SetActiveVersion's Stream parameter.</PackageReleaseNotes>
<PackageReleaseNotes>Updated to API library 10.2.0.</PackageReleaseNotes>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<CodeAnalysisRuleSet>../../build/analyzers.ruleset</CodeAnalysisRuleSet>
@@ -88,7 +88,7 @@ namespace Tgstation.Server.Host.Components.Chat
readonly object synchronizationLock;
/// <summary>
/// The <see cref="ICustomCommandHandler"/> for the <see cref="ChangeChannels(long, IEnumerable{Api.Models.ChatChannel}, CancellationToken)"/>.
/// The <see cref="ICustomCommandHandler"/> for the <see cref="ChangeChannels(long, IEnumerable{Models.ChatChannel}, CancellationToken)"/>.
/// </summary>
ICustomCommandHandler customCommandHandler;
@@ -175,7 +175,7 @@ namespace Tgstation.Server.Host.Components.Chat
}
/// <inheritdoc />
public async Task ChangeChannels(long connectionId, IEnumerable<Api.Models.ChatChannel> newChannels, CancellationToken cancellationToken)
public async Task ChangeChannels(long connectionId, IEnumerable<Models.ChatChannel> newChannels, CancellationToken cancellationToken)
{
if (newChannels == null)
throw new ArgumentNullException(nameof(newChannels));
@@ -554,7 +554,7 @@ namespace Tgstation.Server.Host.Components.Chat
async Task RemapProvider(IProvider provider, CancellationToken cancellationToken)
{
logger.LogTrace("Remapping channels for provider reconnection...");
IEnumerable<Api.Models.ChatChannel> channelsToMap;
IEnumerable<Models.ChatChannel> channelsToMap;
long providerId;
lock (providers)
providerId = providers.Where(x => x.Value == provider).Select(x => x.Key).First();
@@ -40,10 +40,10 @@ namespace Tgstation.Server.Host.Components.Chat
/// Change chat channels.
/// </summary>
/// <param name="connectionId">The <see cref="Api.Models.EntityId.Id"/> of the connection.</param>
/// <param name="newChannels">An <see cref="IEnumerable{T}"/> of the new list of <see cref="Api.Models.ChatChannel"/>s.</param>
/// <param name="newChannels">An <see cref="IEnumerable{T}"/> of the new list of <see cref="Models.ChatChannel"/>s.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
Task ChangeChannels(long connectionId, IEnumerable<Api.Models.ChatChannel> newChannels, CancellationToken cancellationToken);
Task ChangeChannels(long connectionId, IEnumerable<Models.ChatChannel> newChannels, CancellationToken cancellationToken);
/// <summary>
/// Queue a chat <paramref name="message"/> to a given set of <paramref name="channelIds"/>.
@@ -608,14 +608,14 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
}
/// <inheritdoc />
protected override async Task<IReadOnlyCollection<Tuple<Api.Models.ChatChannel, ChannelRepresentation>>> MapChannelsImpl(IEnumerable<Api.Models.ChatChannel> channels, CancellationToken cancellationToken)
protected override async Task<IReadOnlyCollection<Tuple<Models.ChatChannel, ChannelRepresentation>>> MapChannelsImpl(IEnumerable<Models.ChatChannel> channels, CancellationToken cancellationToken)
{
if (channels == null)
throw new ArgumentNullException(nameof(channels));
var remapRequired = false;
async Task<Tuple<Api.Models.ChatChannel, ChannelRepresentation>> GetModelChannelFromDBChannel(Api.Models.ChatChannel channelFromDB)
async Task<Tuple<Models.ChatChannel, ChannelRepresentation>> GetModelChannelFromDBChannel(Models.ChatChannel channelFromDB)
{
if (!channelFromDB.DiscordChannelId.HasValue)
throw new InvalidOperationException("ChatChannel missing DiscordChannelId!");
@@ -33,7 +33,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
Task InitialConnectionJob { get; }
/// <summary>
/// Indicate to the provider that at least one <see cref="MapChannels(IEnumerable{Api.Models.ChatChannel}, CancellationToken)"/> call has successfully completed.
/// Indicate to the provider that at least one <see cref="MapChannels(IEnumerable{ChatChannel}, CancellationToken)"/> call has successfully completed.
/// </summary>
void InitialMappingComplete();
@@ -42,7 +42,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the next available <see cref="Message"/> or <see langword="null"/> if the <see cref="IProvider"/> needed to reconnect.</returns>
/// <remarks>Note that private messages will come in the form of <see cref="ChannelRepresentation"/>s not returned in <see cref="MapChannels(IEnumerable{Api.Models.ChatChannel}, CancellationToken)"/>. Do not <see cref="IDisposable.Dispose"/> the <see cref="IProvider"/> on continuations run from the returned <see cref="Task"/>.</remarks>
/// <remarks>Note that private messages will come in the form of <see cref="ChannelRepresentation"/>s not returned in <see cref="MapChannels(IEnumerable{ChatChannel}, CancellationToken)"/>. Do not <see cref="IDisposable.Dispose"/> the <see cref="IProvider"/> on continuations run from the returned <see cref="Task"/>.</remarks>
Task<Message> NextMessage(CancellationToken cancellationToken);
/// <summary>
@@ -57,8 +57,8 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
/// </summary>
/// <param name="channels">The <see cref="Api.Models.ChatChannel"/>s to map.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in a <see cref="IReadOnlyCollection{T}"/> of the <see cref="Api.Models.ChatChannel"/>'s <see cref="ChannelRepresentation"/>s representing <paramref name="channels"/>.</returns>
Task<IReadOnlyCollection<Tuple<Api.Models.ChatChannel, ChannelRepresentation>>> MapChannels(IEnumerable<Api.Models.ChatChannel> channels, CancellationToken cancellationToken);
/// <returns>A <see cref="Task{TResult}"/> resulting in a <see cref="IReadOnlyCollection{T}"/> of the <see cref="ChatChannel"/>'s <see cref="ChannelRepresentation"/>s representing <paramref name="channels"/>.</returns>
Task<IReadOnlyCollection<Tuple<ChatChannel, ChannelRepresentation>>> MapChannels(IEnumerable<ChatChannel> channels, CancellationToken cancellationToken);
/// <summary>
/// Send a message to the <see cref="IProvider"/>.
@@ -252,8 +252,8 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
}
/// <inheritdoc />
protected override Task<IReadOnlyCollection<Tuple<ChatChannel, ChannelRepresentation>>> MapChannelsImpl(
IEnumerable<ChatChannel> channels,
protected override Task<IReadOnlyCollection<Tuple<Models.ChatChannel, ChannelRepresentation>>> MapChannelsImpl(
IEnumerable<Models.ChatChannel> channels,
CancellationToken cancellationToken)
=> Task.Factory.StartNew(
() =>
@@ -285,10 +285,10 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
else
client.RfcJoin(channelToJoin);
return (IReadOnlyCollection<Tuple<ChatChannel, ChannelRepresentation>>)channels
.Select(apiChannel =>
return (IReadOnlyCollection<Tuple<Models.ChatChannel, ChannelRepresentation>>)channels
.Select(dbChannel =>
{
var channelName = apiChannel.GetIrcChannelName();
var channelName = dbChannel.GetIrcChannelName();
ulong? id = null;
if (!channelIdMap.Any(y =>
{
@@ -303,15 +303,15 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
}
return Tuple.Create(
apiChannel,
dbChannel,
new ChannelRepresentation
{
RealId = id.Value,
IsAdminChannel = apiChannel.IsAdminChannel == true,
IsAdminChannel = dbChannel.IsAdminChannel == true,
ConnectionName = address,
FriendlyName = channelIdMap[id.Value],
IsPrivateChannel = false,
Tag = apiChannel.Tag,
Tag = dbChannel.Tag,
});
})
.ToList();
@@ -117,7 +117,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
public void InitialMappingComplete() => initialConnectionTcs.TrySetResult(null);
/// <inheritdoc />
public async Task<IReadOnlyCollection<Tuple<Api.Models.ChatChannel, ChannelRepresentation>>> MapChannels(IEnumerable<Api.Models.ChatChannel> channels, CancellationToken cancellationToken)
public async Task<IReadOnlyCollection<Tuple<ChatChannel, ChannelRepresentation>>> MapChannels(IEnumerable<ChatChannel> channels, CancellationToken cancellationToken)
{
try
{
@@ -193,13 +193,13 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
protected abstract Task DisconnectImpl(CancellationToken cancellationToken);
/// <summary>
/// Implementation of <see cref="MapChannels(IEnumerable{Api.Models.ChatChannel}, CancellationToken)"/>.
/// Implementation of <see cref="MapChannels(IEnumerable{ChatChannel}, CancellationToken)"/>.
/// </summary>
/// <param name="channels">The <see cref="Api.Models.ChatChannel"/>s to map.</param>
/// <param name="channels">The <see cref="ChatChannel"/>s to map.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in a <see cref="IReadOnlyCollection{T}"/> of the <see cref="Api.Models.ChatChannel"/>'s <see cref="ChannelRepresentation"/>s representing <paramref name="channels"/>.</returns>
protected abstract Task<IReadOnlyCollection<Tuple<Api.Models.ChatChannel, ChannelRepresentation>>> MapChannelsImpl(
IEnumerable<Api.Models.ChatChannel> channels,
/// <returns>A <see cref="Task{TResult}"/> resulting in a <see cref="IReadOnlyCollection{T}"/> of the <see cref="ChatChannel"/>'s <see cref="ChannelRepresentation"/>s representing <paramref name="channels"/>.</returns>
protected abstract Task<IReadOnlyCollection<Tuple<ChatChannel, ChannelRepresentation>>> MapChannelsImpl(
IEnumerable<ChatChannel> channels,
CancellationToken cancellationToken);
/// <summary>
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
@@ -57,16 +58,39 @@ namespace Tgstation.Server.Host.Controllers
/// Converts <paramref name="api"/> to a <see cref="ChatChannel"/>.
/// </summary>
/// <param name="api">The <see cref="Api.Models.ChatChannel"/>. </param>
/// <param name="chatProvider">The channel's <see cref="ChatProvider"/>.</param>
/// <returns>A <see cref="ChatChannel"/> based on <paramref name="api"/>.</returns>
static Models.ChatChannel ConvertApiChatChannel(Api.Models.ChatChannel api) => new ()
static Models.ChatChannel ConvertApiChatChannel(Api.Models.ChatChannel api, ChatProvider chatProvider)
{
DiscordChannelId = api.DiscordChannelId,
IrcChannel = api.IrcChannel,
IsAdminChannel = api.IsAdminChannel ?? false,
IsWatchdogChannel = api.IsWatchdogChannel ?? false,
IsUpdatesChannel = api.IsUpdatesChannel ?? false,
Tag = api.Tag,
};
var result = new Models.ChatChannel
{
#pragma warning disable CS0618
DiscordChannelId = api.DiscordChannelId,
IrcChannel = api.IrcChannel,
#pragma warning restore CS0618
IsAdminChannel = api.IsAdminChannel ?? false,
IsWatchdogChannel = api.IsWatchdogChannel ?? false,
IsUpdatesChannel = api.IsUpdatesChannel ?? false,
Tag = api.Tag,
};
if (api.ChannelData != null)
{
switch (chatProvider)
{
case ChatProvider.Discord:
result.DiscordChannelId = ulong.Parse(api.ChannelData, CultureInfo.InvariantCulture);
break;
case ChatProvider.Irc:
result.IrcChannel = api.ChannelData;
break;
default:
throw new InvalidOperationException($"Invalid chat provider: {chatProvider}");
}
}
return result;
}
/// <summary>
/// Create a new chat bot <paramref name="model"/>.
@@ -106,7 +130,7 @@ namespace Tgstation.Server.Host.Controllers
Name = model.Name,
ConnectionString = model.ConnectionString,
Enabled = model.Enabled,
Channels = model.Channels?.Select(x => ConvertApiChatChannel(x)).ToList() ?? new List<Models.ChatChannel>(), // important that this isn't null
Channels = model.Channels?.Select(x => ConvertApiChatChannel(x, model.Provider.Value)).ToList() ?? new List<Models.ChatChannel>(), // important that this isn't null
InstanceId = Instance.Id.Value,
Provider = model.Provider,
ReconnectionInterval = model.ReconnectionInterval,
@@ -319,7 +343,7 @@ namespace Tgstation.Server.Host.Controllers
DatabaseContext.ChatChannels.RemoveRange(current.Channels);
if (hasChannels)
{
var dbChannels = model.Channels.Select(x => ConvertApiChatChannel(x)).ToList();
var dbChannels = model.Channels.Select(x => ConvertApiChatChannel(x, model.Provider ?? current.Provider.Value)).ToList();
DatabaseContext.ChatChannels.AddRange(dbChannels);
current.Channels = dbChannels;
}
@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using Tgstation.Server.Api.Models;
using Tgstation.Server.Host.Models;
namespace Tgstation.Server.Host.Extensions
{
+1 -1
View File
@@ -33,7 +33,7 @@ namespace Tgstation.Server.Host.Models
/// <inheritdoc />
public ChatBotResponse ToApi() => new ChatBotResponse
{
Channels = Channels.Select(x => x.ToApi()).ToList(),
Channels = Channels.Select(x => x.ToApi(Provider.Value)).ToList(),
ConnectionString = ConnectionString,
Enabled = Enabled,
Provider = Provider,
@@ -1,7 +1,12 @@
namespace Tgstation.Server.Host.Models
using System.ComponentModel.DataAnnotations;
using Tgstation.Server.Api.Models;
using Tgstation.Server.Api.Models.Internal;
namespace Tgstation.Server.Host.Models
{
/// <inheritdoc />
public sealed class ChatChannel : Api.Models.ChatChannel, IApiTransformable<Api.Models.ChatChannel>
public sealed class ChatChannel : ChatChannelBase
{
/// <summary>
/// The row Id.
@@ -9,23 +14,41 @@
public long Id { get; set; }
/// <summary>
/// The <see cref="Api.Models.EntityId.Id"/>.
/// The <see cref="EntityId.Id"/>.
/// </summary>
public long ChatSettingsId { get; set; }
/// <summary>
/// See <see cref="Api.Models.ChatChannel.IrcChannel"/>.
/// </summary>
[StringLength(Limits.MaximumIndexableStringLength, MinimumLength = 1)]
public string IrcChannel { get; set; }
/// <summary>
/// See <see cref="Api.Models.ChatChannel.DiscordChannelId"/>.
/// </summary>
public ulong? DiscordChannelId { get; set; }
/// <summary>
/// The <see cref="ChatBot"/>.
/// </summary>
public ChatBot ChatSettings { get; set; }
/// <inheritdoc />
public Api.Models.ChatChannel ToApi() => new Api.Models.ChatChannel
/// <summary>
/// Convert to a <see cref="Api.Models.ChatChannel"/>.
/// </summary>
/// <param name="chatProvider">The channel's <see cref="ChatProvider"/>.</param>
/// <returns>The converted <see cref="Api.Models.ChatChannel"/>.</returns>
public Api.Models.ChatChannel ToApi(ChatProvider chatProvider) => new Api.Models.ChatChannel
{
ChannelData = chatProvider == ChatProvider.Discord ? DiscordChannelId.ToString() : IrcChannel,
#pragma warning disable CS0618
IrcChannel = IrcChannel,
DiscordChannelId = DiscordChannelId,
#pragma warning restore CS0618
IsAdminChannel = IsAdminChannel,
IsWatchdogChannel = IsWatchdogChannel,
IsUpdatesChannel = IsUpdatesChannel,
IrcChannel = IrcChannel,
Tag = Tag,
};
}
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
@@ -81,7 +81,10 @@ namespace Tgstation.Server.Tests.Instance
IsUpdatesChannel = true,
IsWatchdogChannel = true,
Tag = "butt2",
IrcChannel = channelId
ChannelData = channelId,
#pragma warning disable CS0618
IrcChannel = "should_not_be_this!!!JHF*WW(#*(*$&(#*@))("
#pragma warning restore CS0618
}
}
}, cancellationToken);
@@ -93,8 +96,11 @@ namespace Tgstation.Server.Tests.Instance
Assert.AreEqual(true, updatedBot.Channels.First().IsUpdatesChannel);
Assert.AreEqual(true, updatedBot.Channels.First().IsWatchdogChannel);
Assert.AreEqual("butt2", updatedBot.Channels.First().Tag);
#pragma warning disable CS0618
Assert.AreEqual(channelId, updatedBot.Channels.First().IrcChannel);
Assert.IsNull(updatedBot.Channels.First().DiscordChannelId);
#pragma warning restore CS0618
Assert.AreEqual(channelId, updatedBot.Channels.First().ChannelData);
}
async Task RunDiscord(CancellationToken cancellationToken)
@@ -138,17 +144,6 @@ namespace Tgstation.Server.Tests.Instance
Assert.AreEqual(true, updatedBot.Enabled);
var channelId = UInt64.Parse(Environment.GetEnvironmentVariable("TGS_TEST_DISCORD_CHANNEL"));
firstBot.Channels = new List<ChatChannel>
{
new ChatChannel
{
IsAdminChannel = true,
IsUpdatesChannel = true,
IsWatchdogChannel = true,
Tag = "butt",
DiscordChannelId = channelId
}
};
updatedBot = await chatClient.Update(new ChatBotUpdateRequest
{
@@ -161,7 +156,10 @@ namespace Tgstation.Server.Tests.Instance
IsUpdatesChannel = true,
IsWatchdogChannel = true,
Tag = "butt",
DiscordChannelId = channelId
ChannelData = channelId.ToString(),
#pragma warning disable CS0618
DiscordChannelId = 1234,
#pragma warning restore CS0618
}
}
}, cancellationToken);
@@ -173,8 +171,11 @@ namespace Tgstation.Server.Tests.Instance
Assert.AreEqual(true, updatedBot.Channels.First().IsUpdatesChannel);
Assert.AreEqual(true, updatedBot.Channels.First().IsWatchdogChannel);
Assert.AreEqual("butt", updatedBot.Channels.First().Tag);
#pragma warning disable CS0618
Assert.AreEqual(channelId, updatedBot.Channels.First().DiscordChannelId);
Assert.IsNull(updatedBot.Channels.First().IrcChannel);
#pragma warning restore CS0618
Assert.AreEqual(channelId.ToString(), updatedBot.Channels.First().ChannelData);
}
public async Task RunPostTest(CancellationToken cancellationToken)
@@ -215,7 +216,7 @@ namespace Tgstation.Server.Tests.Instance
IsUpdatesChannel = false,
IsWatchdogChannel = true,
Tag = "butt",
DiscordChannelId = discordBotReq.Channels.First().DiscordChannelId
ChannelData = discordBotReq.Channels.First().ChannelData
});
await ApiAssert.ThrowsException<ApiConflictException>(() => chatClient.Update(discordBotReq, cancellationToken), ErrorCode.ChatBotMaxChannels);
@@ -204,13 +204,9 @@ static class Program
IsWatchdogChannel = providerInfo.WatchdogChannels.Any(x => NormalizeChannelId(x) == channelIdentifier),
IsAdminChannel = providerInfo.AdminChannels.Any(x => NormalizeChannelId(x) == channelIdentifier),
IsUpdatesChannel = providerInfo.DevChannels.Any(x => NormalizeChannelId(x) == channelIdentifier),
ChannelData = channelIdentifier,
};
if (isDiscordProvider)
newChatChannel.DiscordChannelId = ulong.Parse(channelIdentifier);
else
newChatChannel.IrcChannel = channelIdentifier;
createRequest.Channels.Add(newChatChannel);
}