diff --git a/Examples/HostedCommandsBot/HostedCommandsBot.csproj b/Examples/HostedCommandsBot/HostedCommandsBot.csproj
index 2bc3e66d..5343840f 100644
--- a/Examples/HostedCommandsBot/HostedCommandsBot.csproj
+++ b/Examples/HostedCommandsBot/HostedCommandsBot.csproj
@@ -2,7 +2,7 @@
Exe
- netcoreapp3.1
+ net9.0
TehGM.Wolfringo.Examples.HostedCommandsBot
diff --git a/Examples/HostedCommandsBot/Program.cs b/Examples/HostedCommandsBot/Program.cs
index 38332eb2..ed8d2145 100644
--- a/Examples/HostedCommandsBot/Program.cs
+++ b/Examples/HostedCommandsBot/Program.cs
@@ -31,7 +31,7 @@ static void Main(string[] args)
// add wolf client
services.AddWolfClient()
/** Commented methods below override configuration from appsettings.json and appsecrets.json - use them if you want to override, or do not use config files **/
- //.SetCredentials("login", "password") -- sets bot credentials. Note: it's recommended to not use this method,
+ //.SetCredentials("login", "password", "api key") -- sets bot credentials. Note: it's recommended to not use this method,
// and stick to config file that is excluded from the repository - such as appsettings.json in this example
//.SetAutoReconnectAttempts(15) -- sets auto reconnect attempts limit
//.SetAutoReconnectDelay(TimeSpan.FromSeconds(1)) -- sets delay between auto reconnect attempts
diff --git a/Examples/HostedCommandsBot/appsecrets-example.json b/Examples/HostedCommandsBot/appsecrets-example.json
index e3e678d4..a3a55f88 100644
--- a/Examples/HostedCommandsBot/appsecrets-example.json
+++ b/Examples/HostedCommandsBot/appsecrets-example.json
@@ -2,6 +2,7 @@
"WolfClient": {
"LoginUsername": "MyBotUsername",
"LoginPassword": "MyBotPassword",
- "LoginType": "Email"
+ "LoginType": "Email",
+ "ApiKey": "MyBotApiKey"
}
}
diff --git a/Examples/HostedPingBot/Program.cs b/Examples/HostedPingBot/Program.cs
index 0cde88be..8c6594bd 100644
--- a/Examples/HostedPingBot/Program.cs
+++ b/Examples/HostedPingBot/Program.cs
@@ -26,7 +26,7 @@ static void Main(string[] args)
services.Configure(context.Configuration.GetSection("WolfClient"));
services.AddWolfClient()
/** Commented methods below override configuration from appsettings.json and appsecrets.json - use them if you want to override, or do not use config files **/
- //.SetCredentials("login", "password") -- sets bot credentials. Note: it's recommended to not use this method,
+ //.SetCredentials("login", "password", "api key") -- sets bot credentials. Note: it's recommended to not use this method,
// and stick to config file that is excluded from the repository - such as appsettings.json in this example
//.SetAutoReconnectAttempts(15) -- sets auto reconnect attempts limit
//.SetAutoReconnectDelay(TimeSpan.FromSeconds(1)) -- sets delay between auto reconnect attempts
diff --git a/Examples/HostedPingBot/appsecrets-example.json b/Examples/HostedPingBot/appsecrets-example.json
index e3e678d4..a3a55f88 100644
--- a/Examples/HostedPingBot/appsecrets-example.json
+++ b/Examples/HostedPingBot/appsecrets-example.json
@@ -2,6 +2,7 @@
"WolfClient": {
"LoginUsername": "MyBotUsername",
"LoginPassword": "MyBotPassword",
- "LoginType": "Email"
+ "LoginType": "Email",
+ "ApiKey": "MyBotApiKey"
}
}
diff --git a/Examples/SimpleCommandsBot/Config.cs b/Examples/SimpleCommandsBot/Config.cs
index 7dea234a..0531a289 100644
--- a/Examples/SimpleCommandsBot/Config.cs
+++ b/Examples/SimpleCommandsBot/Config.cs
@@ -12,6 +12,8 @@ class Config
public string Username { get; private set; }
[JsonProperty("password")]
public string Password { get; private set; }
+ [JsonProperty("apiKey")]
+ public string ApiKey { get; private set; }
public static Config Load()
=> JsonConvert.DeserializeObject(File.ReadAllText("appsecrets.json"));
diff --git a/Examples/SimpleCommandsBot/Program.cs b/Examples/SimpleCommandsBot/Program.cs
index 80f80246..312a0f33 100644
--- a/Examples/SimpleCommandsBot/Program.cs
+++ b/Examples/SimpleCommandsBot/Program.cs
@@ -19,6 +19,8 @@ static async Task Main(string[] args)
// create client with builder
_client = new WolfClientBuilder()
+ // configure API Key
+ .WithApiKey(Config.Load().ApiKey)
// add logging
.WithLogging(CreateLoggerFactory())
// add commands
diff --git a/Examples/SimpleCommandsBot/appsecrets-example.json b/Examples/SimpleCommandsBot/appsecrets-example.json
index f0604bdd..1e44ced9 100644
--- a/Examples/SimpleCommandsBot/appsecrets-example.json
+++ b/Examples/SimpleCommandsBot/appsecrets-example.json
@@ -1,4 +1,5 @@
{
"username": "MyBotUsername",
- "password": "MyBotPassword"
+ "password": "MyBotPassword",
+ "apiKey": "MyBotApiKey"
}
diff --git a/Examples/SimplePingBot/Config.cs b/Examples/SimplePingBot/Config.cs
index 1db8befb..5bc5d55e 100644
--- a/Examples/SimplePingBot/Config.cs
+++ b/Examples/SimplePingBot/Config.cs
@@ -12,6 +12,8 @@ class Config
public string Username { get; private set; }
[JsonProperty("password")]
public string Password { get; private set; }
+ [JsonProperty("apiKey")]
+ public string ApiKey { get; private set; }
public static Config Load()
=> JsonConvert.DeserializeObject(File.ReadAllText("appsecrets.json"));
diff --git a/Examples/SimplePingBot/Program.cs b/Examples/SimplePingBot/Program.cs
index a30cc73f..47c7aeb6 100644
--- a/Examples/SimplePingBot/Program.cs
+++ b/Examples/SimplePingBot/Program.cs
@@ -20,8 +20,9 @@ static async Task Main(string[] args)
// optional: create a logger
ILogger log = CreateLogger();
- // create client and listen to events we're interested in
+ // create client, set API Key and listen to events we're interested in
_client = new WolfClientBuilder()
+ .WithApiKey(Config.Load().ApiKey)
.WithLogging(log)
.Build();
_client.MessageReceived += OnMessageReceived; // This event is raised when client receives and parses any message type.
diff --git a/Examples/SimplePingBot/appsecrets-example.json b/Examples/SimplePingBot/appsecrets-example.json
index f0604bdd..1e44ced9 100644
--- a/Examples/SimplePingBot/appsecrets-example.json
+++ b/Examples/SimplePingBot/appsecrets-example.json
@@ -1,4 +1,5 @@
{
"username": "MyBotUsername",
- "password": "MyBotPassword"
+ "password": "MyBotPassword",
+ "apiKey": "MyBotApiKey"
}
diff --git a/Wolfringo.Commands/Wolfringo.Commands.csproj b/Wolfringo.Commands/Wolfringo.Commands.csproj
index 68ce5d00..a8015950 100644
--- a/Wolfringo.Commands/Wolfringo.Commands.csproj
+++ b/Wolfringo.Commands/Wolfringo.Commands.csproj
@@ -3,7 +3,7 @@
netstandard2.0;net9.0
TehGM.Wolfringo.Commands
- 2.2.0
+ 2.2.1
TehGM
Wolfringo
Commands System for Wolfringo library.
@@ -18,8 +18,7 @@
2.2.0.0
2.2.0.0
- - Add support for Link and Image preview embeds;
- - Chat Messages and retrieved chat histories will now have Embeds property properly populated;
+Compatibility patch for Wolfringo 2.2.1.
NUGET_README.md
diff --git a/Wolfringo.Core/Messages/MessageEventNames.cs b/Wolfringo.Core/Messages/MessageEventNames.cs
index 6113231e..b651c3cc 100644
--- a/Wolfringo.Core/Messages/MessageEventNames.cs
+++ b/Wolfringo.Core/Messages/MessageEventNames.cs
@@ -120,5 +120,7 @@ public static class MessageEventNames
public const string TipAdd = "tip add";
/// WOLF Protocol Event name for .
public const string MetadataUrl = "metadata url";
+ /// WOLF Protocol Event name for .
+ public const string Objection = "objection";
}
}
diff --git a/Wolfringo.Core/Messages/Serialization/MessageSerializerProviderOptions.cs b/Wolfringo.Core/Messages/Serialization/MessageSerializerProviderOptions.cs
index e76b3ffb..f938f367 100644
--- a/Wolfringo.Core/Messages/Serialization/MessageSerializerProviderOptions.cs
+++ b/Wolfringo.Core/Messages/Serialization/MessageSerializerProviderOptions.cs
@@ -71,6 +71,7 @@ public MessageSerializerProviderOptions()
{ MessageEventNames.TipSummary, new DefaultMessageSerializer() },
{ MessageEventNames.TipDetail, new DefaultMessageSerializer() },
{ MessageEventNames.MetadataUrl, new DefaultMessageSerializer() },
+ { MessageEventNames.Objection, new DefaultMessageSerializer() },
// group join and leave
{ MessageEventNames.GroupMemberAdd, new GroupJoinLeaveMessageSerializer() },
{ MessageEventNames.GroupMemberDelete, new GroupJoinLeaveMessageSerializer() },
diff --git a/Wolfringo.Core/Messages/Types/ObjectionEvent.cs b/Wolfringo.Core/Messages/Types/ObjectionEvent.cs
new file mode 100644
index 00000000..d008c7dd
--- /dev/null
+++ b/Wolfringo.Core/Messages/Types/ObjectionEvent.cs
@@ -0,0 +1,25 @@
+using Newtonsoft.Json;
+
+namespace TehGM.Wolfringo.Messages
+{
+ /// Represents a WOLF objection error.
+ public class ObjectionEvent : IWolfMessage
+ {
+ ///
+ /// Equals to .
+ [JsonIgnore]
+ public string EventName => MessageEventNames.Objection;
+
+ /// Error message.
+ [JsonProperty("message")]
+ public string Message { get; private set; }
+ /// Time in seconds to wait before reconnecting.
+ /// Value of -1 indicates no reconnect.
+ [JsonProperty("reconnectSeconds")]
+ public int ReconnectSeconds { get; private set; }
+
+ /// Creates a message instance.
+ [JsonConstructor]
+ protected ObjectionEvent() { }
+ }
+}
diff --git a/Wolfringo.Core/WolfClient.cs b/Wolfringo.Core/WolfClient.cs
index 5b529df3..3c79ea99 100644
--- a/Wolfringo.Core/WolfClient.cs
+++ b/Wolfringo.Core/WolfClient.cs
@@ -58,6 +58,8 @@ public class WolfClient : IWolfClient, IWolfClientCacheAccessor, IDisposable
protected bool IgnoreOwnChatMessages { get; }
/// Token used with the connection.
protected string Token { get; }
+ /// API Key used to connect.
+ protected string ApiKey { get; }
/// Socket client used by this WOLF client.
protected ISocketClient SocketClient { get; }
/// Callbacks dispatcher used by this WOLF client.
@@ -108,6 +110,7 @@ public WolfClient(IServiceProvider services, WolfClientOptions options)
this.IgnoreOwnChatMessages = options.IgnoreOwnChatMessages;
this.Url = options.ServerURL;
this.Device = options.Device;
+ this.ApiKey = options.ApiKey;
this.Token = tokenProvider.GetToken();
// init dispatcher
@@ -187,8 +190,9 @@ public async Task ConnectAsync(WolfDevice device, CancellationToken cancellation
this.Clear();
await this.Cache.OnConnectingAsync(this, cancellationToken).ConfigureAwait(false);
this._connectionCts = new CancellationTokenSource();
+ string path = $"/socket.io/?token={this.Token}&device={device.ToString().ToLowerInvariant()}&EIO=3&transport=websocket&apiKey={this.ApiKey}";
await this.SocketClient.ConnectAsync(
- new Uri(new Uri(this.Url), $"/socket.io/?token={this.Token}&device={device.ToString().ToLowerInvariant()}&EIO=3&transport=websocket"),
+ new Uri(new Uri(this.Url), path),
cancellationToken).ConfigureAwait(false);
}
@@ -419,6 +423,8 @@ private async void OnClientMessageReceived(object sender, SocketMessageEventArgs
// if welcome is already logged in, we can populate userID
if (msg is WelcomeEvent welcome && welcome.LoggedInUser != null)
this.CurrentUserID = welcome.LoggedInUser.ID;
+ else if (msg is ObjectionEvent objection)
+ this.Log?.LogError("Server objected: {Message}", objection.Message);
// cache
if (this.Cache != null)
diff --git a/Wolfringo.Core/WolfClientBuilder.cs b/Wolfringo.Core/WolfClientBuilder.cs
index 05b2c3d0..37cf8bf3 100644
--- a/Wolfringo.Core/WolfClientBuilder.cs
+++ b/Wolfringo.Core/WolfClientBuilder.cs
@@ -126,6 +126,17 @@ public WolfClientBuilder WithBetaServerURL()
public WolfClientBuilder WithDevice(WolfDevice device)
=> this.ConfigureOptions(options => options.Device = device);
+ // API KEY
+ /// Sets API Key to connect with.
+ /// API Key to connect with.
+ /// Current builder instance.
+ public WolfClientBuilder WithApiKey(string apiKey)
+ {
+ if (string.IsNullOrWhiteSpace(apiKey))
+ throw new ArgumentNullException(nameof(apiKey));
+ return this.ConfigureOptions(options => options.ApiKey = apiKey);
+ }
+
/// Allows configuring options for Wolf Client.
/// Delegate that can be used for options configuration.
/// Current builder instance.
diff --git a/Wolfringo.Core/WolfClientOptions.cs b/Wolfringo.Core/WolfClientOptions.cs
index 858b9a9a..15df889b 100644
--- a/Wolfringo.Core/WolfClientOptions.cs
+++ b/Wolfringo.Core/WolfClientOptions.cs
@@ -10,6 +10,8 @@ public class WolfClientOptions
/// Default device to pass to the server when connecting.
public const WolfDevice DefaultDevice = WolfDevice.Bot;
+ /// API Key to connect with. Must match the account that will be used to connect.
+ public string ApiKey { get; set; }
/// WOLF server URL to connect to.
public string ServerURL { get; set; } = DefaultServerURL;
/// Device to connect as.
diff --git a/Wolfringo.Core/Wolfringo.Core.csproj b/Wolfringo.Core/Wolfringo.Core.csproj
index af926828..64a49779 100644
--- a/Wolfringo.Core/Wolfringo.Core.csproj
+++ b/Wolfringo.Core/Wolfringo.Core.csproj
@@ -3,7 +3,7 @@
netstandard2.0;netstandard2.1;net5.0;net9.0
TehGM.Wolfringo
- 2.2.0
+ 2.2.1
TehGM
Wolfringo
https://github.com/TehGM/Wolfringo
@@ -11,25 +11,15 @@
A .NET Library for WOLF (previously Palringo)
https://wolfringo.tehgm.net
true
- 2.2.0.0
- 2.2.0.0
+ 2.2.1.0
+ 2.2.1.0
MIT
git
false
wolf palringo wolfringo pal bot client
wolfringo_logo.png
- - Add IChatEmbedDeserializer to allow deserialization of chat embeds;
- - Add support for Link and Image preview embeds;
- - Chat Messages and retrieved chat histories will now have Embeds property properly populated;
- - ChatMessageSendingOptions provide 2 predefined statics: DisableEmbeds and DisableLinkDetection;
- - Update UrlMetadataMessage to use headers with version 2;
- - Fix an error when a message containing an embed is received;
- - Fix link metadata message not having a serializer registered with the provider;
- - ChatMessageSerializer now has a constructor that takes a IChatEmbedDeserializer;
- - ChatHistoryResponseSerializer now has a constructor that takes a IChatEmbedDeserializer;
- - Removed unnecessary locks in CommandsSystem, MessageSerializerProvider and ResponseSerializerProvider;
- - BuildDefaultServiceProvider protected methods are marked as obsolete in WolfClient and CommandsSystem;
+ - Support connecting with API Key.
NUGET_README.md
diff --git a/Wolfringo.Hosting/HostedWolfClient.cs b/Wolfringo.Hosting/HostedWolfClient.cs
index 028edce0..0e44d6de 100644
--- a/Wolfringo.Hosting/HostedWolfClient.cs
+++ b/Wolfringo.Hosting/HostedWolfClient.cs
@@ -137,7 +137,8 @@ private void CreateClient()
{
IgnoreOwnChatMessages = options.IgnoreOwnChatMessages,
Device = options.Device,
- ServerURL = options.ServerURL
+ ServerURL = options.ServerURL,
+ ApiKey = options.ApiKey
});
// sub to events
diff --git a/Wolfringo.Hosting/HostedWolfClientOptions.cs b/Wolfringo.Hosting/HostedWolfClientOptions.cs
index 5ef821e0..fff20101 100644
--- a/Wolfringo.Hosting/HostedWolfClientOptions.cs
+++ b/Wolfringo.Hosting/HostedWolfClientOptions.cs
@@ -19,6 +19,8 @@ public class HostedWolfClientOptions
/// Whether the hosted client should automatically login when connected.
/// Defaults to true.
public bool AutoLogin { get; set; } = true;
+ /// API Key to connect with. Must match the account that will be used to connect.
+ public string ApiKey { get; set; }
/// Username to use as login when automatically logging in.
public string LoginUsername { get; set; }
/// Password to authenticate with when automatically logging in.
diff --git a/Wolfringo.Hosting/WolfClientServiceCollectionExtensions.cs b/Wolfringo.Hosting/WolfClientServiceCollectionExtensions.cs
index 1ccc2f7d..c21d82e8 100644
--- a/Wolfringo.Hosting/WolfClientServiceCollectionExtensions.cs
+++ b/Wolfringo.Hosting/WolfClientServiceCollectionExtensions.cs
@@ -64,11 +64,25 @@ public static IHostedWolfClientServiceBuilder AddWolfClient(this IServiceCollect
///
///
///
+ [Obsolete("WOLF is making changes to require API Key to connect. Use overload that accepts API Key as a parameter")]
public static IHostedWolfClientServiceBuilder SetCredentials(this IHostedWolfClientServiceBuilder builder, string login, string password, WolfLoginType loginType = WolfLoginType.Email)
+ => builder.SetCredentials(login, password, null, loginType);
+
+ /// Sets login credentials.
+ /// Hosted WOLF Client Service builder.
+ /// Login.
+ /// Password.
+ /// API Key. Must match API Key assigned for this user.
+ /// Login Type.
+ ///
+ ///
+ ///
+ public static IHostedWolfClientServiceBuilder SetCredentials(this IHostedWolfClientServiceBuilder builder, string login, string password, string apiKey, WolfLoginType loginType = WolfLoginType.Email)
=> builder.Configure(options =>
{
options.LoginUsername = login;
options.LoginPassword = password;
+ options.ApiKey = apiKey;
options.LoginType = loginType;
});
diff --git a/Wolfringo.Hosting/Wolfringo.Hosting.csproj b/Wolfringo.Hosting/Wolfringo.Hosting.csproj
index fbd85758..4a8ecf64 100644
--- a/Wolfringo.Hosting/Wolfringo.Hosting.csproj
+++ b/Wolfringo.Hosting/Wolfringo.Hosting.csproj
@@ -2,7 +2,7 @@
netstandard2.0;netcoreapp3.0;net9.0
- 2.2.0
+ 2.2.1
TehGM
Copyright (c) 2020 TehGM
https://wolfringo.tehgm.net
@@ -17,7 +17,7 @@
2.0.0.0
2.0.0.0
-Compatibility patch for Wolfringo 2.2.0.
+ - Support connecting with API Key.
NUGET_README.md
diff --git a/Wolfringo/Wolfringo.nuspec b/Wolfringo/Wolfringo.nuspec
index b598a246..bd84e36b 100644
--- a/Wolfringo/Wolfringo.nuspec
+++ b/Wolfringo/Wolfringo.nuspec
@@ -2,7 +2,7 @@
Wolfringo
- 2.2.0
+ 2.2.1
Wolfringo
TehGM
TehGM
@@ -16,24 +16,14 @@
true
Copyright (c) 2020 TehGM
- - Add IChatEmbedDeserializer to allow deserialization of chat embeds;
- - Add support for Link and Image preview embeds;
- - Chat Messages and retrieved chat histories will now have Embeds property properly populated;
- - ChatMessageSendingOptions provide 2 predefined statics: DisableEmbeds and DisableLinkDetection;
- - Update UrlMetadataMessage to use headers with version 2;
- - Fix an error when a message containing an embed is received;
- - Fix link metadata message not having a serializer registered with the provider;
- - ChatMessageSerializer now has a constructor that takes a IChatEmbedDeserializer;
- - ChatHistoryResponseSerializer now has a constructor that takes a IChatEmbedDeserializer;
- - Removed unnecessary locks in CommandsSystem, MessageSerializerProvider and ResponseSerializerProvider;
- - BuildDefaultServiceProvider protected methods are marked as obsolete in WolfClient and CommandsSystem;
+ - Support connecting with API Key.
-
+
-
+
diff --git a/docs/guides/getting-started/connecting-bot.md b/docs/guides/getting-started/connecting-bot.md
index 2082fe03..d95ed1b0 100644
--- a/docs/guides/getting-started/connecting-bot.md
+++ b/docs/guides/getting-started/connecting-bot.md
@@ -3,7 +3,9 @@ uid: Guides.GettingStarted.Connecting
---
# Connecting the bot
-Once Wolfringo is [installed](xref:Guides.GettingStarted.Installation), it's time to get your bot connected. The way to do it varies whether you're using Wolfringo.Hosting package or not.
+Once Wolfringo is [installed](xref:Guides.GettingStarted.Installation), it's time to get your bot connected. The way to do it varies whether you're using Wolfringo.Hosting package or not.
+In either case you need an account for the bot, its login and password, and also an API Key which you can get by having your bot approved on [\[bot approval\]](http://wolflive.com/bot+approval?r=80280172) or [\[bot approval.ar\]](http://wolflive.com/bot+approval.ar?r=80280172).
+If you provide invalid credentials or API Key, the bot will output an error when trying to connect.
### [Without Wolfringo.Hosting (Normal Bot)](#tab/connecting-normal-bot)
First, add following using directives to your Program.cs:
@@ -40,7 +42,11 @@ static async Task MainAsync(string[] args)
Now we need to do a few things - create a WolfClient instance using a builder, register event listeners, connect the bot, and prevent application from exiting. To do this, you can use following code inside of your MainAsync method:
```csharp
// create client and listen to events we're interested in
-_client = new WolfClientBuilder().Build();
+_client = new WolfClientBuilder()
+ // note: it is recommended to not hardcode API key, and use .gitignore-d config file instead
+ // see exaple project linked below for a full example!
+ .WithApiKey("ApiKey")
+ .Build();
// these will show error for now - don't worry, we'll handle that in a moment!
_client.AddMessageListener(OnWelcome);
_client.AddMessageListener(OnChatMessage);
@@ -124,7 +130,7 @@ services.Configure(context.Configuration.GetSection("Wo
// note: it is recommended to not hardcode username and password, and use .gitignore-d config file instead
// see exaple project linked below for a full example!
services.AddWolfClient()
- .SetCredentials("BotEmail", "BotPassword", WolfLoginType.Email);
+ .SetCredentials("BotEmail", "BotPassword", WolfLoginType.Email, "ApiKey");
// add our HostedMessageHandler
services.AddHostedService();
@@ -156,7 +162,7 @@ IHost host = Host.CreateDefaultBuilder(args)
// add client
// note: it is recommended to not hardcode username and password, and use .gitignore-d config file instead
// see exaple project linked below for a full example!
- .SetCredentials("BotEmail", "BotPassword", WolfLoginType.Email);
+ .SetCredentials("BotEmail", "BotPassword", WolfLoginType.Email, "ApiKey");
// add our HostedMessageHandler
services.AddHostedService();
@@ -176,7 +182,7 @@ host.RunAsync().GetAwaiter().GetResult();
Unlike bots without .NET Generic Host, @TehGM.Wolfringo.Hosting.HostedWolfClient automatically handles reconnection internally. By default it'll attempt to reconnect 5 times. You can change that by either changing "AutoReconnectAttempts" in [settings](https://github.com/TehGM/Wolfringo/blob/master/Examples/HostedPingBot/appsettings.json), or using following method:
```csharp highlight="3"
services.AddWolfClient()
- .SetCredentials("BotEmail", "BotPassword", WolfLoginType.Email)
+ .SetCredentials("BotEmail", "BotPassword", WolfLoginType.Email, "ApiKey")
.SetAutoReconnectAttempts(-1); // by default, bot will try to reconnect 5 times - here we change it to -1, which makes it infinite
```
> [!TIP]