updated some stuff

This commit is contained in:
EmotionChild 2022-05-18 01:09:25 +12:00
parent 94324f4d4a
commit ad0916477b
5 changed files with 1052 additions and 1049 deletions

3
.gitignore vendored
View file

@ -362,5 +362,8 @@ MigrationBackup/
# Fody - auto-generated XML schema # Fody - auto-generated XML schema
FodyWeavers.xsd FodyWeavers.xsd
# Manually added folders
Windows-x64/ Windows-x64/
Linux-x64/ Linux-x64/
.idea
.vs

View file

@ -8,100 +8,100 @@ using Microsoft.Extensions.Logging;
namespace SupportChild.Commands namespace SupportChild.Commands
{ {
public class AddCommand : BaseCommandModule public class AddCommand : BaseCommandModule
{ {
[Command("add")] [Command("add")]
[Description("Adds a user to a ticket.")] [Description("Adds a user to a ticket.")]
public async Task OnExecute(CommandContext command, [RemainingText] string commandArgs) public async Task OnExecute(CommandContext command, [RemainingText] string commandArgs)
{ {
// Check if the user has permission to use this command. // Check if the user has permission to use this command.
if (!Config.HasPermission(command.Member, "add")) if (!Config.HasPermission(command.Member, "add"))
{ {
DiscordEmbed error = new DiscordEmbedBuilder DiscordEmbed error = new DiscordEmbedBuilder
{ {
Color = DiscordColor.Red, Color = DiscordColor.Red,
Description = "You do not have permission to use this command." Description = "You do not have permission to use this command."
}; };
await command.RespondAsync(error); await command.RespondAsync(error);
command.Client.Logger.Log(LogLevel.Information, "User tried to use the add command but did not have permission."); command.Client.Logger.Log(LogLevel.Information, "User tried to use the add command but did not have permission.");
return; return;
} }
// Check if ticket exists in the database // Check if ticket exists in the database
if (!Database.IsOpenTicket(command.Channel.Id)) if (!Database.IsOpenTicket(command.Channel.Id))
{ {
DiscordEmbed error = new DiscordEmbedBuilder DiscordEmbed error = new DiscordEmbedBuilder
{ {
Color = DiscordColor.Red, Color = DiscordColor.Red,
Description = "This channel is not a ticket." Description = "This channel is not a ticket."
}; };
await command.RespondAsync(error); await command.RespondAsync(error);
return; return;
} }
string[] parsedArgs = Utilities.ParseIDs(command.RawArgumentString); string[] parsedArgs = Utilities.ParseIDs(command.RawArgumentString);
foreach (string parsedArg in parsedArgs) foreach (string parsedArg in parsedArgs)
{ {
if (!ulong.TryParse(parsedArg, out ulong userID)) if (!ulong.TryParse(parsedArg, out ulong userID))
{ {
DiscordEmbed error = new DiscordEmbedBuilder DiscordEmbed error = new DiscordEmbedBuilder
{ {
Color = DiscordColor.Red, Color = DiscordColor.Red,
Description = "Invalid ID/Mention. (Could not convert to numerical)" Description = "Invalid ID/Mention. (Could not convert to numerical)"
}; };
await command.RespondAsync(error); await command.RespondAsync(error);
continue; continue;
} }
DiscordMember mentionedMember; DiscordMember mentionedMember;
try try
{ {
mentionedMember = await command.Guild.GetMemberAsync(userID); mentionedMember = await command.Guild.GetMemberAsync(userID);
} }
catch (Exception) catch (Exception)
{ {
DiscordEmbed error = new DiscordEmbedBuilder DiscordEmbed error = new DiscordEmbedBuilder
{ {
Color = DiscordColor.Red, Color = DiscordColor.Red,
Description = "Invalid ID/Mention. (Could not find user on this server)" Description = "Invalid ID/Mention. (Could not find user on this server)"
}; };
await command.RespondAsync(error); await command.RespondAsync(error);
continue; continue;
} }
try try
{ {
await command.Channel.AddOverwriteAsync(mentionedMember, Permissions.AccessChannels, Permissions.None); await command.Channel.AddOverwriteAsync(mentionedMember, Permissions.AccessChannels, Permissions.None);
DiscordEmbed message = new DiscordEmbedBuilder DiscordEmbed message = new DiscordEmbedBuilder
{ {
Color = DiscordColor.Green, Color = DiscordColor.Green,
Description = "Added " + mentionedMember.Mention + " to ticket." Description = "Added " + mentionedMember.Mention + " to ticket."
}; };
await command.RespondAsync(message); await command.RespondAsync(message);
// Log it if the log channel exists // Log it if the log channel exists
DiscordChannel logChannel = command.Guild.GetChannel(Config.logChannel); DiscordChannel logChannel = command.Guild.GetChannel(Config.logChannel);
if (logChannel != null) if (logChannel != null)
{ {
DiscordEmbed logMessage = new DiscordEmbedBuilder DiscordEmbed logMessage = new DiscordEmbedBuilder
{ {
Color = DiscordColor.Green, Color = DiscordColor.Green,
Description = mentionedMember.Mention + " was added to " + command.Channel.Mention + Description = mentionedMember.Mention + " was added to " + command.Channel.Mention +
" by " + command.Member.Mention + "." " by " + command.Member.Mention + "."
}; };
await logChannel.SendMessageAsync(logMessage); await logChannel.SendMessageAsync(logMessage);
} }
} }
catch (Exception) catch (Exception)
{ {
DiscordEmbed message = new DiscordEmbedBuilder DiscordEmbed message = new DiscordEmbedBuilder
{ {
Color = DiscordColor.Red, Color = DiscordColor.Red,
Description = "Could not add <@" + parsedArg + "> to ticket, unknown error occured." Description = "Could not add <@" + parsedArg + "> to ticket, unknown error occured."
}; };
await command.RespondAsync(message); await command.RespondAsync(message);
} }
} }
} }
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -12,296 +12,296 @@ using Microsoft.Extensions.Logging;
namespace SupportChild namespace SupportChild
{ {
internal class EventHandler internal class EventHandler
{ {
private DiscordClient discordClient; private DiscordClient discordClient;
//DateTime for the end of the cooldown //DateTime for the end of the cooldown
private static Dictionary<ulong, DateTime> reactionTicketCooldowns = new Dictionary<ulong, DateTime>(); private static Dictionary<ulong, DateTime> reactionTicketCooldowns = new Dictionary<ulong, DateTime>();
public EventHandler(DiscordClient client) public EventHandler(DiscordClient client)
{ {
discordClient = client; this.discordClient = client;
} }
internal Task OnReady(DiscordClient client, ReadyEventArgs e) internal Task OnReady(DiscordClient client, ReadyEventArgs e)
{ {
discordClient.Logger.Log(LogLevel.Information, "Client is ready to process events."); discordClient.Logger.Log(LogLevel.Information, "Client is ready to process events.");
// Checking activity type // Checking activity type
if (!Enum.TryParse(Config.presenceType, true, out ActivityType activityType)) if (!Enum.TryParse(Config.presenceType, true, out ActivityType activityType))
{ {
Console.WriteLine("Presence type '" + Config.presenceType + "' invalid, using 'Playing' instead."); Console.WriteLine("Presence type '" + Config.presenceType + "' invalid, using 'Playing' instead.");
activityType = ActivityType.Playing; activityType = ActivityType.Playing;
} }
discordClient.UpdateStatusAsync(new DiscordActivity(Config.presenceText, activityType), UserStatus.Online); this.discordClient.UpdateStatusAsync(new DiscordActivity(Config.presenceText, activityType), UserStatus.Online);
return Task.CompletedTask; return Task.CompletedTask;
} }
internal Task OnGuildAvailable(DiscordClient client, GuildCreateEventArgs e) internal Task OnGuildAvailable(DiscordClient client, GuildCreateEventArgs e)
{ {
discordClient.Logger.Log(LogLevel.Information, $"Guild available: {e.Guild.Name}"); discordClient.Logger.Log(LogLevel.Information, $"Guild available: {e.Guild.Name}");
IReadOnlyDictionary<ulong, DiscordRole> roles = e.Guild.Roles; IReadOnlyDictionary<ulong, DiscordRole> roles = e.Guild.Roles;
foreach ((ulong roleID, DiscordRole role) in roles) foreach ((ulong roleID, DiscordRole role) in roles)
{ {
discordClient.Logger.Log(LogLevel.Information, role.Name.PadRight(40, '.') + roleID); discordClient.Logger.Log(LogLevel.Information, role.Name.PadRight(40, '.') + roleID);
} }
return Task.CompletedTask; return Task.CompletedTask;
} }
internal Task OnClientError(DiscordClient client, ClientErrorEventArgs e) internal Task OnClientError(DiscordClient client, ClientErrorEventArgs e)
{ {
discordClient.Logger.Log(LogLevel.Error, $"Exception occured: {e.Exception.GetType()}: {e.Exception}"); discordClient.Logger.Log(LogLevel.Error, $"Exception occured: {e.Exception.GetType()}: {e.Exception}");
return Task.CompletedTask; return Task.CompletedTask;
} }
internal async Task OnMessageCreated(DiscordClient client, MessageCreateEventArgs e) internal async Task OnMessageCreated(DiscordClient client, MessageCreateEventArgs e)
{ {
if (e.Author.IsBot) if (e.Author.IsBot)
{ {
return; return;
} }
// Check if ticket exists in the database and ticket notifications are enabled // Check if ticket exists in the database and ticket notifications are enabled
if (!Database.TryGetOpenTicket(e.Channel.Id, out Database.Ticket ticket) || !Config.ticketUpdatedNotifications) if (!Database.TryGetOpenTicket(e.Channel.Id, out Database.Ticket ticket) || !Config.ticketUpdatedNotifications)
{ {
return; return;
} }
// Sends a DM to the assigned staff member if at least a day has gone by since the last message and the user sending the message isn't staff // Sends a DM to the assigned staff member if at least a day has gone by since the last message and the user sending the message isn't staff
IReadOnlyList<DiscordMessage> messages = await e.Channel.GetMessagesAsync(2); IReadOnlyList<DiscordMessage> messages = await e.Channel.GetMessagesAsync(2);
if (messages.Count > 1 && messages[1].Timestamp < DateTimeOffset.UtcNow.AddDays(Config.ticketUpdatedNotificationDelay * -1) && !Database.IsStaff(e.Author.Id)) if (messages.Count > 1 && messages[1].Timestamp < DateTimeOffset.UtcNow.AddDays(Config.ticketUpdatedNotificationDelay * -1) && !Database.IsStaff(e.Author.Id))
{ {
try try
{ {
DiscordEmbed message = new DiscordEmbedBuilder DiscordEmbed message = new DiscordEmbedBuilder
{ {
Color = DiscordColor.Green, Color = DiscordColor.Green,
Description = "A ticket you are assigned to has been updated: " + e.Channel.Mention Description = "A ticket you are assigned to has been updated: " + e.Channel.Mention
}; };
DiscordMember staffMember = await e.Guild.GetMemberAsync(ticket.assignedStaffID); DiscordMember staffMember = await e.Guild.GetMemberAsync(ticket.assignedStaffID);
await staffMember.SendMessageAsync(message); await staffMember.SendMessageAsync(message);
} }
catch (NotFoundException) { } catch (NotFoundException) { }
catch (UnauthorizedException) { } catch (UnauthorizedException) { }
} }
} }
internal Task OnCommandError(CommandsNextExtension commandSystem, CommandErrorEventArgs e) internal Task OnCommandError(CommandsNextExtension commandSystem, CommandErrorEventArgs e)
{ {
switch (e.Exception) switch (e.Exception)
{ {
case CommandNotFoundException _: case CommandNotFoundException _:
return Task.CompletedTask; return Task.CompletedTask;
case ChecksFailedException _: case ChecksFailedException _:
{ {
foreach (CheckBaseAttribute attr in ((ChecksFailedException)e.Exception).FailedChecks) foreach (CheckBaseAttribute attr in ((ChecksFailedException)e.Exception).FailedChecks)
{ {
DiscordEmbed error = new DiscordEmbedBuilder DiscordEmbed error = new DiscordEmbedBuilder
{ {
Color = DiscordColor.Red, Color = DiscordColor.Red,
Description = ParseFailedCheck(attr) Description = this.ParseFailedCheck(attr)
}; };
e.Context?.Channel?.SendMessageAsync(error); e.Context?.Channel?.SendMessageAsync(error);
} }
return Task.CompletedTask; return Task.CompletedTask;
} }
default: default:
{ {
discordClient.Logger.Log(LogLevel.Error, $"Exception occured: {e.Exception.GetType()}: {e.Exception}"); discordClient.Logger.Log(LogLevel.Error, $"Exception occured: {e.Exception.GetType()}: {e.Exception}");
DiscordEmbed error = new DiscordEmbedBuilder DiscordEmbed error = new DiscordEmbedBuilder
{ {
Color = DiscordColor.Red, Color = DiscordColor.Red,
Description = "Internal error occured, please report this to the developer." Description = "Internal error occured, please report this to the developer."
}; };
e.Context?.Channel?.SendMessageAsync(error); e.Context?.Channel?.SendMessageAsync(error);
return Task.CompletedTask; return Task.CompletedTask;
} }
} }
} }
internal async Task OnReactionAdded(DiscordClient client, MessageReactionAddEventArgs e) internal async Task OnReactionAdded(DiscordClient client, MessageReactionAddEventArgs e)
{ {
if (e.Message.Id != Config.reactionMessage) return; if (e.Message.Id != Config.reactionMessage) return;
DiscordGuild guild = e.Message.Channel.Guild; DiscordGuild guild = e.Message.Channel.Guild;
DiscordMember member = await guild.GetMemberAsync(e.User.Id); DiscordMember member = await guild.GetMemberAsync(e.User.Id);
if (!Config.HasPermission(member, "new") || Database.IsBlacklisted(member.Id)) return; if (!Config.HasPermission(member, "new") || Database.IsBlacklisted(member.Id)) return;
if (reactionTicketCooldowns.ContainsKey(member.Id)) if (reactionTicketCooldowns.ContainsKey(member.Id))
{ {
if (reactionTicketCooldowns[member.Id] > DateTime.Now) return; // cooldown has not expired if (reactionTicketCooldowns[member.Id] > DateTime.Now) return; // cooldown has not expired
else reactionTicketCooldowns.Remove(member.Id); // cooldown exists but has expired, delete it else reactionTicketCooldowns.Remove(member.Id); // cooldown exists but has expired, delete it
} }
DiscordChannel category = guild.GetChannel(Config.ticketCategory); DiscordChannel category = guild.GetChannel(Config.ticketCategory);
DiscordChannel ticketChannel = await guild.CreateChannelAsync("ticket", ChannelType.Text, category); DiscordChannel ticketChannel = await guild.CreateChannelAsync("ticket", ChannelType.Text, category);
if (ticketChannel == null) return; if (ticketChannel == null) return;
ulong staffID = 0; ulong staffID = 0;
if (Config.randomAssignment) if (Config.randomAssignment)
{ {
staffID = Database.GetRandomActiveStaff(0)?.userID ?? 0; staffID = Database.GetRandomActiveStaff(0)?.userID ?? 0;
} }
long id = Database.NewTicket(member.Id, staffID, ticketChannel.Id); long id = Database.NewTicket(member.Id, staffID, ticketChannel.Id);
reactionTicketCooldowns.Add(member.Id, DateTime.Now.AddSeconds(10)); // add a cooldown which expires in 10 seconds reactionTicketCooldowns.Add(member.Id, DateTime.Now.AddSeconds(10)); // add a cooldown which expires in 10 seconds
string ticketID = id.ToString("00000"); string ticketID = id.ToString("00000");
await ticketChannel.ModifyAsync(model => model.Name = "ticket-" + ticketID); await ticketChannel.ModifyAsync(model => model.Name = "ticket-" + ticketID);
await ticketChannel.AddOverwriteAsync(member, Permissions.AccessChannels, Permissions.None); await ticketChannel.AddOverwriteAsync(member, Permissions.AccessChannels, Permissions.None);
await ticketChannel.SendMessageAsync("Hello, " + member.Mention + "!\n" + Config.welcomeMessage); await ticketChannel.SendMessageAsync("Hello, " + member.Mention + "!\n" + Config.welcomeMessage);
// Remove user's reaction // Remove user's reaction
await e.Message.DeleteReactionAsync(e.Emoji, e.User); await e.Message.DeleteReactionAsync(e.Emoji, e.User);
// Refreshes the channel as changes were made to it above // Refreshes the channel as changes were made to it above
ticketChannel = await SupportChild.GetClient().GetChannelAsync(ticketChannel.Id); ticketChannel = await SupportChild.GetClient().GetChannelAsync(ticketChannel.Id);
if (staffID != 0) if (staffID != 0)
{ {
DiscordEmbed assignmentMessage = new DiscordEmbedBuilder DiscordEmbed assignmentMessage = new DiscordEmbedBuilder
{ {
Color = DiscordColor.Green, Color = DiscordColor.Green,
Description = "Ticket was randomly assigned to <@" + staffID + ">." Description = "Ticket was randomly assigned to <@" + staffID + ">."
}; };
await ticketChannel.SendMessageAsync(assignmentMessage); await ticketChannel.SendMessageAsync(assignmentMessage);
if (Config.assignmentNotifications) if (Config.assignmentNotifications)
{ {
DiscordEmbed message = new DiscordEmbedBuilder DiscordEmbed message = new DiscordEmbedBuilder
{ {
Color = DiscordColor.Green, Color = DiscordColor.Green,
Description = "You have been randomly assigned to a newly opened support ticket: " + Description = "You have been randomly assigned to a newly opened support ticket: " +
ticketChannel.Mention ticketChannel.Mention
}; };
try try
{ {
DiscordMember staffMember = await guild.GetMemberAsync(staffID); DiscordMember staffMember = await guild.GetMemberAsync(staffID);
await staffMember.SendMessageAsync(message); await staffMember.SendMessageAsync(message);
} }
catch (NotFoundException) catch (NotFoundException)
{ {
} }
catch (UnauthorizedException) catch (UnauthorizedException)
{ {
} }
} }
} }
// Log it if the log channel exists // Log it if the log channel exists
DiscordChannel logChannel = guild.GetChannel(Config.logChannel); DiscordChannel logChannel = guild.GetChannel(Config.logChannel);
if (logChannel != null) if (logChannel != null)
{ {
DiscordEmbed logMessage = new DiscordEmbedBuilder DiscordEmbed logMessage = new DiscordEmbedBuilder
{ {
Color = DiscordColor.Green, Color = DiscordColor.Green,
Description = "Ticket " + ticketChannel.Mention + " opened by " + member.Mention + ".\n", Description = "Ticket " + ticketChannel.Mention + " opened by " + member.Mention + ".\n",
Footer = new DiscordEmbedBuilder.EmbedFooter { Text = "Ticket " + ticketID } Footer = new DiscordEmbedBuilder.EmbedFooter {Text = "Ticket " + ticketID}
}; };
await logChannel.SendMessageAsync(logMessage); await logChannel.SendMessageAsync(logMessage);
} }
} }
internal async Task OnMemberAdded(DiscordClient client, GuildMemberAddEventArgs e) internal async Task OnMemberAdded(DiscordClient client, GuildMemberAddEventArgs e)
{ {
if (!Database.TryGetOpenTickets(e.Member.Id, out List<Database.Ticket> ownTickets)) if (!Database.TryGetOpenTickets(e.Member.Id, out List<Database.Ticket> ownTickets))
{ {
return; return;
} }
foreach (Database.Ticket ticket in ownTickets) foreach (Database.Ticket ticket in ownTickets)
{ {
try try
{ {
DiscordChannel channel = await client.GetChannelAsync(ticket.channelID); DiscordChannel channel = await client.GetChannelAsync(ticket.channelID);
if (channel?.GuildId == e.Guild.Id) if (channel?.GuildId == e.Guild.Id)
{ {
await channel.AddOverwriteAsync(e.Member, Permissions.AccessChannels, Permissions.None); await channel.AddOverwriteAsync(e.Member, Permissions.AccessChannels, Permissions.None);
DiscordEmbed message = new DiscordEmbedBuilder() DiscordEmbed message = new DiscordEmbedBuilder()
.WithColor(DiscordColor.Green) .WithColor(DiscordColor.Green)
.WithDescription("User '" + e.Member.Username + "#" + e.Member.Discriminator + "' has rejoined the server, and has been re-added to the ticket."); .WithDescription("User '" + e.Member.Username + "#" + e.Member.Discriminator + "' has rejoined the server, and has been re-added to the ticket.");
await channel.SendMessageAsync(message); await channel.SendMessageAsync(message);
} }
} }
catch (Exception) { } catch (Exception) { }
} }
} }
internal async Task OnMemberRemoved(DiscordClient client, GuildMemberRemoveEventArgs e) internal async Task OnMemberRemoved(DiscordClient client, GuildMemberRemoveEventArgs e)
{ {
if (Database.TryGetOpenTickets(e.Member.Id, out List<Database.Ticket> ownTickets)) if (Database.TryGetOpenTickets(e.Member.Id, out List<Database.Ticket> ownTickets))
{ {
foreach (Database.Ticket ticket in ownTickets) foreach(Database.Ticket ticket in ownTickets)
{ {
try try
{ {
DiscordChannel channel = await client.GetChannelAsync(ticket.channelID); DiscordChannel channel = await client.GetChannelAsync(ticket.channelID);
if (channel?.GuildId == e.Guild.Id) if (channel?.GuildId == e.Guild.Id)
{ {
DiscordEmbed message = new DiscordEmbedBuilder() DiscordEmbed message = new DiscordEmbedBuilder()
.WithColor(DiscordColor.Red) .WithColor(DiscordColor.Red)
.WithDescription("User '" + e.Member.Username + "#" + e.Member.Discriminator + "' has left the server."); .WithDescription("User '" + e.Member.Username + "#" + e.Member.Discriminator + "' has left the server.");
await channel.SendMessageAsync(message); await channel.SendMessageAsync(message);
} }
} }
catch (Exception) { } catch (Exception) { }
} }
} }
if (Database.TryGetAssignedTickets(e.Member.Id, out List<Database.Ticket> assignedTickets) && Config.logChannel != 0) if (Database.TryGetAssignedTickets(e.Member.Id, out List<Database.Ticket> assignedTickets) && Config.logChannel != 0)
{ {
DiscordChannel logChannel = await client.GetChannelAsync(Config.logChannel); DiscordChannel logChannel = await client.GetChannelAsync(Config.logChannel);
if (logChannel != null) if (logChannel != null)
{ {
foreach (Database.Ticket ticket in assignedTickets) foreach (Database.Ticket ticket in assignedTickets)
{ {
try try
{ {
DiscordChannel channel = await client.GetChannelAsync(ticket.channelID); DiscordChannel channel = await client.GetChannelAsync(ticket.channelID);
if (channel?.GuildId == e.Guild.Id) if (channel?.GuildId == e.Guild.Id)
{ {
DiscordEmbed message = new DiscordEmbedBuilder() DiscordEmbed message = new DiscordEmbedBuilder()
.WithColor(DiscordColor.Red) .WithColor(DiscordColor.Red)
.WithDescription("Assigned staff member '" + e.Member.Username + "#" + e.Member.Discriminator + "' has left the server: <#" + channel.Id + ">"); .WithDescription("Assigned staff member '" + e.Member.Username + "#" + e.Member.Discriminator + "' has left the server: <#" + channel.Id + ">");
await logChannel.SendMessageAsync(message); await logChannel.SendMessageAsync(message);
} }
} }
catch (Exception) { } catch (Exception) { }
} }
} }
} }
} }
private string ParseFailedCheck(CheckBaseAttribute attr) private string ParseFailedCheck(CheckBaseAttribute attr)
{ {
switch (attr) switch (attr)
{ {
case CooldownAttribute _: case CooldownAttribute _:
return "You cannot use do that so often!"; return "You cannot use do that so often!";
case RequireOwnerAttribute _: case RequireOwnerAttribute _:
return "Only the server owner can use that command!"; return "Only the server owner can use that command!";
case RequirePermissionsAttribute _: case RequirePermissionsAttribute _:
return "You don't have permission to do that!"; return "You don't have permission to do that!";
case RequireRolesAttribute _: case RequireRolesAttribute _:
return "You do not have a required role!"; return "You do not have a required role!";
case RequireUserPermissionsAttribute _: case RequireUserPermissionsAttribute _:
return "You don't have permission to do that!"; return "You don't have permission to do that!";
case RequireNsfwAttribute _: case RequireNsfwAttribute _:
return "This command can only be used in an NSFW channel!"; return "This command can only be used in an NSFW channel!";
default: default:
return "Unknown Discord API error occured, please try again later."; return "Unknown Discord API error occured, please try again later.";
} }
} }
} }
} }

View file

@ -1,84 +1,84 @@
bot: bot:
# Bot token. # Bot token.
token: "<add-token-here>" token: "<add-token-here>"
# Command prefix. # Command prefix.
prefix: "-" prefix: "-"
# Channel where ticket logs are posted (recommended) # Channel where ticket logs are posted (recommended)
log-channel: 000000000000000000 log-channel: 000000000000000000
# Category where the ticket will be created, it will have the same permissions of that ticket plus read permissions for the user opening the ticket (recommended) # Category where the ticket will be created, it will have the same permissions of that ticket plus read permissions for the user opening the ticket (recommended)
ticket-category: 000000000000000000 ticket-category: 000000000000000000
# A message which will open new tickets when users react to it (optional) # A message which will open new tickets when users react to it (optional)
reaction-message: 000000000000000000 reaction-message: 000000000000000000
# Message posted when a ticket is opened. # Message posted when a ticket is opened.
welcome-message: "Please describe your issue below, and include all information needed for us to help you." welcome-message: "Please describe your issue below, and include all information needed for us to help you."
# Decides what messages are shown in console # Decides what messages are shown in console
# Possible values are: Critical, Error, Warning, Information, Debug. # Possible values are: Critical, Error, Warning, Information, Debug.
console-log-level: "Information" console-log-level: "Information"
# Format for timestamps in transcripts and google sheets if used # Format for timestamps in transcripts and google sheets if used
timestamp-format: "yyyy-MM-dd HH:mm" timestamp-format: "yyyy-MM-dd HH:mm"
# Whether or not staff members should be randomly assigned tickets when they are made. Individual staff members can opt out using the toggleactive command. # Whether or not staff members should be randomly assigned tickets when they are made. Individual staff members can opt out using the toggleactive command.
random-assignment: true random-assignment: true
# If set to true the rasssign command will include staff members set as inactive if a specific role is specified in the command. # If set to true the rasssign command will include staff members set as inactive if a specific role is specified in the command.
# This can be useful if you have admins set as inactive to not automatically recieve tickets and then have moderators elevate tickets when needed. # This can be useful if you have admins set as inactive to not automatically recieve tickets and then have moderators elevate tickets when needed.
random-assign-role-override: true random-assign-role-override: true
# Sets the type of activity for the bot to display in its presence status # Sets the type of activity for the bot to display in its presence status
# Possible values are: Playing, Streaming, ListeningTo, Watching, Competing # Possible values are: Playing, Streaming, ListeningTo, Watching, Competing
presence-type: "ListeningTo" presence-type: "ListeningTo"
# Sets the activity text shown in the bot's status # Sets the activity text shown in the bot's status
presence-text: "-new" presence-text: "-new"
notifications: notifications:
# Notifies the assigned staff member when a new message is posted in a ticket if the ticket has been silent for a configurable amount of time # Notifies the assigned staff member when a new message is posted in a ticket if the ticket has been silent for a configurable amount of time
# Other staff members and bots do not trigger this. # Other staff members and bots do not trigger this.
ticket-updated: true ticket-updated: true
# The above notification will only be sent if the ticket has been silent for more than this amount of days. Default is 0.5 days. # The above notification will only be sent if the ticket has been silent for more than this amount of days. Default is 0.5 days.
ticket-updated-delay: 0.5 ticket-updated-delay: 0.5
# Notifies staff when they are assigned to tickets # Notifies staff when they are assigned to tickets
assignment: true assignment: true
# Notifies the user opening the ticket that their ticket was closed and includes the transcript # Notifies the user opening the ticket that their ticket was closed and includes the transcript
closing: true closing: true
database: database:
# Address and port of the mysql server # Address and port of the mysql server
address: "127.0.0.1" address: "127.0.0.1"
port: 3306 port: 3306
# Name of the database to use # Name of the database to use
name: "supportbot" name: "supportchild"
# Username and password for authentication # Username and password for authentication
user: "" user: ""
password: "" password: ""
# Set up which roles are allowed to use different commands. # Set up which roles are allowed to use different commands.
# Example: # Example:
# new: [ 000000000000000000, 111111111111111111 ] # new: [ 000000000000000000, 111111111111111111 ]
# They are grouped into suggested command groups below for first time setup. # They are grouped into suggested command groups below for first time setup.
permissions: permissions:
# Public commands # Public commands
close: [] close: []
list: [] list: []
new: [] new: []
say: [] say: []
status: [] status: []
summary: [] summary: []
transcript: [] transcript: []
# Moderator commands # Moderator commands
add: [] add: []
addmessage: [] addmessage: []
assign: [] assign: []
blacklist: [] blacklist: []
listassigned: [] listassigned: []
listoldest: [] listoldest: []
listunassigned: [] listunassigned: []
move: [] move: []
rassign: [] rassign: []
removemessage: [] removemessage: []
setsummary: [] setsummary: []
toggleactive: [] toggleactive: []
unassign: [] unassign: []
unblacklist: [] unblacklist: []
# Admin commands # Admin commands
addstaff: [] addstaff: []
reload: [] reload: []
removestaff: [] removestaff: []
setticket: [] setticket: []
unsetticket: [] unsetticket: []