I’m developing a Discord bot using Discord.NET version 0.9, and I’m facing a stack overflow exception whenever I run it. This issue arises when I instantiate my main program class within my functions class. I’m concerned that this may be tied to how I’m managing static instances, but I’m at a loss for the cause of the circular reference. My bot compiles successfully, yet it crashes during execution. Below is the code I’m working with:
MainBot.cs:
using System;
using System.Linq;
using Discord;
using Discord.Commands;
using System.IO;
namespace MyDiscordBot
{
class MainBot
{
CommandHandler commandHandler = new CommandHandler();
public static MainBot _instance = new MainBot();
static void Main(string[] args)
{
new MainBot().Initiate();
}
public DiscordClient _discordClient;
public void Initiate()
{
Console.Title = "My Discord Bot";
_discordClient = new DiscordClient(config =>
{
config.AppName = "MyBot";
config.LogLevel = LogSeverity.Info;
config.LogHandler = LogMessage;
});
_discordClient.UsingCommands(commands =>
{
commands.PrefixChar = '!';
commands.AllowMentionPrefix = true;
commands.HelpMode = HelpMode.Public;
});
var botToken = "YOUR_TOKEN_HERE";
commandHandler.ConfigureCommands(_discordClient);
setupEventHandlers();
_discordClient.ExecuteAndWait(async () =>
{
await _discordClient.Connect(botToken, TokenType.Bot);
SetGameStatus(_discordClient, "!help for commands");
});
}
public void SetGameStatus(DiscordClient client, string status)
{
client.SetGame(status);
}
public void setupEventHandlers()
{
_discordClient.UserJoined += async (sender, eventArgs) =>
{
await eventArgs.Server.GetChannel(123456789).SendMessage($"Welcome {eventArgs.User.Mention} to our server!");
};
}
public void LogMessage(Object sender, LogMessageEventArgs args)
{
Console.WriteLine($"[{args.Severity}] [{args.Source}] {args.Message}");
}
}
}
CommandHandler.cs:
using System;
using System.Threading.Tasks;
using Discord;
using Discord.Commands;
namespace MyDiscordBot
{
class CommandHandler
{
public static CommandHandler _instance = new CommandHandler();
UtilityMethods utilityMethods = new UtilityMethods();
public void ConfigureCommands(DiscordClient client)
{
var commandService = client.GetService<CommandService>();
commandService.CreateCommand("echo")
.Description("Echoes a message")
.Parameter("text", ParameterType.Unparsed)
.Do(async (e) =>
{
await e.Channel.SendMessage($"Echo: {e.GetArg("text")}");
});
commandService.CreateCommand("refresh")
.Description("Refreshes user data")
.Do(async (e) =>
{
if (e.User.ServerPermissions.Administrator)
{
foreach (User member in e.Server.Users)
{
if (!member.IsBot)
utilityMethods.RefreshUserData(member);
}
await e.Channel.SendMessage("Data refresh completed!");
}
else
{
await e.Channel.SendMessage("You don't have permission!");
}
});
}
}
}
UtilityMethods.cs:
using Discord;
using System;
using System.IO;
namespace MyDiscordBot
{
class UtilityMethods
{
MainBot mainBot = new MainBot();
public void RefreshUserData(User user)
{
string userFilePath = @"C:\BotData\Users\" + user.Id + ".txt";
if (File.Exists(userFilePath))
{
File.Delete(userFilePath);
}
string[] userData = { user.Name, GetUserRoles(user) };
File.WriteAllLines(userFilePath, userData);
}
public string GetUserRoles(User user)
{
string roles = "";
foreach (Role userRole in user.Roles)
{
if (userRole.Name != "Admin" && userRole.Name != "@everyone")
{
roles += userRole.Name + "|";
}
}
return roles;
}
public string GetStoredUsername(string userId)
{
string userFilePath = @"C:\BotData\Users\" + userId + ".txt";
if (File.Exists(userFilePath))
{
string[] data = File.ReadAllLines(userFilePath);
return data[0];
}
return null;
}
}
}
The issue occurs when the UtilityMethods class attempts to create a new instance of MainBot. Can anyone suggest what might be triggering this circular reference problem?