2024-12-26 07:12:50 +00:00
using System ;
using System.Collections ;
using System.Collections.Generic ;
using System.Collections.Specialized ;
2024-12-26 04:55:00 +00:00
using System.Linq ;
2024-12-26 07:12:50 +00:00
using System.Text.RegularExpressions ;
using System.Threading.Tasks ;
2024-12-26 07:47:07 +00:00
using DSharpPlus.Commands.Processors.SlashCommands ;
2024-12-26 04:55:00 +00:00
using DSharpPlus.Entities ;
2024-12-26 12:54:28 +00:00
namespace SupportChild.Interviews ;
2024-12-26 04:55:00 +00:00
public static class Interviewer
{
2024-12-27 03:43:55 +00:00
public static async Task < bool > StartInterview ( DiscordChannel channel )
2024-12-26 04:55:00 +00:00
{
2024-12-27 04:23:03 +00:00
if ( ! Database . TryGetInterviewTemplate ( channel . Parent . Id , out InterviewStep template ) )
2024-12-26 06:50:47 +00:00
{
2024-12-27 03:43:55 +00:00
return false ;
2024-12-26 07:12:50 +00:00
}
2024-12-27 04:23:03 +00:00
await SendNextMessage ( channel , template ) ;
2024-12-27 03:43:55 +00:00
return Database . SaveInterview ( channel . Id , template ) ;
}
public static async Task < bool > RestartInterview ( DiscordChannel channel )
{
2024-12-27 04:23:03 +00:00
if ( Database . TryGetInterview ( channel . Id , out InterviewStep interviewRoot ) )
2024-12-26 07:38:17 +00:00
{
2024-12-27 03:43:55 +00:00
if ( Config . deleteMessagesAfterNoSummary )
{
await DeletePreviousMessages ( interviewRoot , channel ) ;
}
if ( ! Database . TryDeleteInterview ( channel . Id ) )
{
Logger . Warn ( "Could not delete interview from database. Channel ID: " + channel . Id ) ;
}
2024-12-26 07:38:17 +00:00
}
2024-12-27 03:43:55 +00:00
return await StartInterview ( channel ) ;
2024-12-26 04:55:00 +00:00
}
2024-12-27 03:43:55 +00:00
public static async Task < bool > StopInterview ( DiscordChannel channel )
2024-12-26 07:47:07 +00:00
{
2024-12-27 04:23:03 +00:00
if ( Database . TryGetInterview ( channel . Id , out InterviewStep interviewRoot ) )
2024-12-26 07:47:07 +00:00
{
2024-12-26 10:47:55 +00:00
if ( Config . deleteMessagesAfterNoSummary )
{
2024-12-27 03:43:55 +00:00
await DeletePreviousMessages ( interviewRoot , channel ) ;
2024-12-26 10:47:55 +00:00
}
2024-12-27 03:43:55 +00:00
if ( ! Database . TryDeleteInterview ( channel . Id ) )
2024-12-26 07:47:07 +00:00
{
2024-12-27 03:43:55 +00:00
Logger . Warn ( "Could not delete interview from database. Channel ID: " + channel . Id ) ;
2024-12-26 07:47:07 +00:00
}
}
2024-12-27 03:43:55 +00:00
return true ;
2024-12-26 07:47:07 +00:00
}
2024-12-26 07:16:18 +00:00
public static async Task ProcessButtonOrSelectorResponse ( DiscordInteraction interaction )
2024-12-26 04:55:00 +00:00
{
2024-12-26 07:12:50 +00:00
if ( interaction ? . Channel = = null | | interaction ? . Message = = null )
2024-12-26 04:55:00 +00:00
{
return ;
}
2024-12-26 07:30:56 +00:00
// Ignore if option was deselected.
2024-12-26 07:51:41 +00:00
if ( interaction . Data . ComponentType is not DiscordComponentType . Button & & interaction . Data . Values . Length = = 0 )
2024-12-26 07:16:18 +00:00
{
2024-12-26 07:30:56 +00:00
await interaction . CreateResponseAsync ( DiscordInteractionResponseType . UpdateMessage ) ;
2024-12-26 07:16:18 +00:00
return ;
}
2024-12-26 07:28:39 +00:00
// Return if there is no active interview in this channel
2024-12-27 04:23:03 +00:00
if ( ! Database . TryGetInterview ( interaction . Channel . Id , out InterviewStep interviewRoot ) )
2024-12-26 04:55:00 +00:00
{
2024-12-26 07:30:56 +00:00
await interaction . CreateResponseAsync ( DiscordInteractionResponseType . ChannelMessageWithSource , new DiscordInteractionResponseBuilder ( )
. AddEmbed ( new DiscordEmbedBuilder ( )
. WithColor ( DiscordColor . Red )
. WithDescription ( "Error: There is no active interview in this ticket, ask an admin to check the bot logs if this seems incorrect." ) )
. AsEphemeral ( ) ) ;
2024-12-26 07:12:50 +00:00
return ;
2024-12-26 04:55:00 +00:00
}
2024-12-26 07:12:50 +00:00
2024-12-26 07:28:39 +00:00
// Return if the current question cannot be found in the interview.
2024-12-27 04:23:03 +00:00
if ( ! interviewRoot . TryGetCurrentStep ( out InterviewStep currentStep ) )
2024-12-26 07:12:50 +00:00
{
2024-12-26 07:30:56 +00:00
await interaction . CreateResponseAsync ( DiscordInteractionResponseType . ChannelMessageWithSource , new DiscordInteractionResponseBuilder ( )
. AddEmbed ( new DiscordEmbedBuilder ( )
. WithColor ( DiscordColor . Red )
. WithDescription ( "Error: Something seems to have broken in this interview, you may want to restart it." ) )
. AsEphemeral ( ) ) ;
2024-12-27 04:23:03 +00:00
Logger . Error ( "The interview for channel " + interaction . Channel . Id + " exists but does not have a message ID set for it's root interview step" ) ;
2024-12-26 07:12:50 +00:00
return ;
}
2024-12-26 07:28:39 +00:00
// Check if this button/selector is for an older question.
2024-12-27 04:23:03 +00:00
if ( interaction . Message . Id ! = currentStep . messageID )
2024-12-26 07:12:50 +00:00
{
2024-12-26 07:30:56 +00:00
await interaction . CreateResponseAsync ( DiscordInteractionResponseType . ChannelMessageWithSource , new DiscordInteractionResponseBuilder ( )
. AddEmbed ( new DiscordEmbedBuilder ( )
. WithColor ( DiscordColor . Red )
. WithDescription ( "Error: You have already replied to this question, you have to reply to the latest one." ) )
. AsEphemeral ( ) ) ;
2024-12-26 07:12:50 +00:00
return ;
}
2024-12-26 07:51:41 +00:00
try
{
await interaction . CreateResponseAsync ( DiscordInteractionResponseType . UpdateMessage ) ;
}
catch ( Exception e )
{
Logger . Error ( "Could not update original message:" , e ) ;
}
2024-12-26 07:32:34 +00:00
2024-12-26 07:28:39 +00:00
// Parse the response index from the button/selector.
2024-12-26 07:16:18 +00:00
string componentID = "" ;
2024-12-26 07:51:41 +00:00
string answer = "" ;
2024-12-26 07:16:18 +00:00
switch ( interaction . Data . ComponentType )
2024-12-26 07:12:50 +00:00
{
2024-12-26 07:51:41 +00:00
case DiscordComponentType . UserSelect :
case DiscordComponentType . RoleSelect :
case DiscordComponentType . ChannelSelect :
case DiscordComponentType . MentionableSelect :
if ( interaction . Data . Resolved ? . Roles ? . Any ( ) ? ? false )
{
answer = interaction . Data . Resolved . Roles . First ( ) . Value . Mention ;
}
else if ( interaction . Data . Resolved ? . Users ? . Any ( ) ? ? false )
{
answer = interaction . Data . Resolved . Users . First ( ) . Value . Mention ;
}
else if ( interaction . Data . Resolved ? . Channels ? . Any ( ) ? ? false )
{
answer = interaction . Data . Resolved . Channels . First ( ) . Value . Mention ;
}
else if ( interaction . Data . Resolved ? . Messages ? . Any ( ) ? ? false )
{
answer = interaction . Data . Resolved . Messages . First ( ) . Value . Id . ToString ( ) ;
}
break ;
2024-12-26 07:16:18 +00:00
case DiscordComponentType . StringSelect :
componentID = interaction . Data . Values [ 0 ] ;
break ;
case DiscordComponentType . Button :
componentID = interaction . Data . CustomId . Replace ( "supportchild_interviewbutton " , "" ) ;
break ;
2024-12-26 10:23:25 +00:00
case DiscordComponentType . ActionRow :
case DiscordComponentType . FormInput :
2024-12-26 07:16:18 +00:00
default :
2024-12-26 10:23:25 +00:00
throw new ArgumentOutOfRangeException ( "Tried to process an invalid component type: " + interaction . Data . ComponentType ) ;
2024-12-26 07:12:50 +00:00
}
2024-12-26 07:51:41 +00:00
// The different mentionable selectors provide the actual answer, while the others just return the ID.
if ( componentID = = "" )
2024-12-26 07:12:50 +00:00
{
2024-12-27 04:23:03 +00:00
foreach ( KeyValuePair < string , InterviewStep > step in currentStep . steps )
2024-12-26 07:51:41 +00:00
{
2024-12-27 04:23:03 +00:00
// Skip to the first matching step.
if ( Regex . IsMatch ( answer , step . Key ) )
2024-12-26 10:27:36 +00:00
{
2024-12-27 04:23:03 +00:00
await HandleAnswer ( answer , step . Value , interviewRoot , currentStep , interaction . Channel ) ;
2024-12-26 10:27:36 +00:00
return ;
}
2024-12-26 07:51:41 +00:00
}
2024-12-26 07:12:50 +00:00
2024-12-27 04:23:03 +00:00
Logger . Error ( "The interview for channel " + interaction . Channel . Id + " reached a step of type " + currentStep . messageType + " which has no valid next step. Their selection was:\n" + answer ) ;
2024-12-26 12:54:28 +00:00
DiscordMessage followupMessage = await interaction . CreateFollowupMessageAsync ( new DiscordFollowupMessageBuilder ( ) . AddEmbed ( new DiscordEmbedBuilder
2024-12-26 10:27:36 +00:00
{
Color = DiscordColor . Red ,
Description = "Error: Could not determine the next question based on your answer. Check your response and ask an admin to check the bot logs if this seems incorrect."
} ) . AsEphemeral ( ) ) ;
2024-12-27 04:23:03 +00:00
currentStep . AddRelatedMessageIDs ( followupMessage . Id ) ;
2024-12-26 12:54:28 +00:00
Database . SaveInterview ( interaction . Channel . Id , interviewRoot ) ;
2024-12-26 07:12:50 +00:00
}
2024-12-26 07:51:41 +00:00
else
{
2024-12-27 04:23:03 +00:00
if ( ! int . TryParse ( componentID , out int stepIndex ) )
2024-12-26 07:51:41 +00:00
{
Logger . Error ( "Invalid interview button/selector index: " + componentID ) ;
return ;
}
2024-12-26 07:12:50 +00:00
2024-12-27 04:23:03 +00:00
if ( stepIndex > = currentStep . steps . Count | | stepIndex < 0 )
2024-12-26 07:51:41 +00:00
{
2024-12-27 04:23:03 +00:00
Logger . Error ( "Invalid interview button/selector index: " + stepIndex ) ;
2024-12-26 07:51:41 +00:00
return ;
}
2024-12-27 04:23:03 +00:00
( string stepString , InterviewStep nextStep ) = currentStep . steps . ElementAt ( stepIndex ) ;
await HandleAnswer ( stepString , nextStep , interviewRoot , currentStep , interaction . Channel ) ;
2024-12-26 07:51:41 +00:00
}
2024-12-26 04:55:00 +00:00
}
2024-12-26 07:32:34 +00:00
public static async Task ProcessResponseMessage ( DiscordMessage answerMessage )
2024-12-26 04:55:00 +00:00
{
2024-12-26 07:12:50 +00:00
// Either the message or the referenced message is null.
2024-12-26 07:32:34 +00:00
if ( answerMessage . Channel = = null | | answerMessage . ReferencedMessage ? . Channel = = null )
2024-12-26 07:12:50 +00:00
{
return ;
}
// The channel does not have an active interview.
2024-12-27 04:23:03 +00:00
if ( ! Database . TryGetInterview ( answerMessage . ReferencedMessage . Channel . Id , out InterviewStep interviewRoot ) )
2024-12-26 07:12:50 +00:00
{
return ;
}
2024-12-27 04:23:03 +00:00
if ( ! interviewRoot . TryGetCurrentStep ( out InterviewStep currentStep ) )
2024-12-26 07:12:50 +00:00
{
return ;
}
// The user responded to something other than the latest interview question.
2024-12-27 04:23:03 +00:00
if ( answerMessage . ReferencedMessage . Id ! = currentStep . messageID )
2024-12-26 07:12:50 +00:00
{
return ;
}
// The user responded to a question which does not take a text response.
2024-12-27 04:23:03 +00:00
if ( currentStep . messageType ! = MessageType . TEXT_INPUT )
2024-12-26 07:12:50 +00:00
{
return ;
}
2024-12-26 07:32:34 +00:00
// The length requirement is less than 1024 characters, and must be less than the configurable limit if it is set.
2024-12-27 04:23:03 +00:00
int maxLength = Math . Min ( currentStep . maxLength ? ? 1024 , 1024 ) ;
2024-12-26 07:32:34 +00:00
if ( answerMessage . Content . Length > maxLength )
{
DiscordMessage lengthMessage = await answerMessage . RespondAsync ( new DiscordEmbedBuilder
{
Description = "Error: Your answer cannot be more than " + maxLength + " characters (" + answerMessage . Content . Length + "/" + maxLength + ")." ,
Color = DiscordColor . Red
} ) ;
2024-12-27 04:23:03 +00:00
currentStep . AddRelatedMessageIDs ( answerMessage . Id , lengthMessage . Id ) ;
2024-12-26 12:54:28 +00:00
Database . SaveInterview ( answerMessage . Channel . Id , interviewRoot ) ;
2024-12-26 07:32:34 +00:00
return ;
}
2024-12-27 04:23:03 +00:00
if ( answerMessage . Content . Length < ( currentStep . minLength ? ? 0 ) )
2024-12-26 07:32:34 +00:00
{
DiscordMessage lengthMessage = await answerMessage . RespondAsync ( new DiscordEmbedBuilder
{
2024-12-27 04:23:03 +00:00
Description = "Error: Your answer must be at least " + currentStep . minLength + " characters (" + answerMessage . Content . Length + "/" + currentStep . minLength + ")." ,
2024-12-26 07:32:34 +00:00
Color = DiscordColor . Red
} ) ;
2024-12-27 04:23:03 +00:00
currentStep . AddRelatedMessageIDs ( answerMessage . Id , lengthMessage . Id ) ;
2024-12-26 12:54:28 +00:00
Database . SaveInterview ( answerMessage . Channel . Id , interviewRoot ) ;
2024-12-26 07:32:34 +00:00
return ;
}
2024-12-27 04:23:03 +00:00
foreach ( ( string stepPattern , InterviewStep nextStep ) in currentStep . steps )
2024-12-26 07:12:50 +00:00
{
2024-12-27 04:23:03 +00:00
// Skip to the first matching step.
if ( ! Regex . IsMatch ( answerMessage . Content , stepPattern ) )
2024-12-26 12:54:28 +00:00
{
continue ;
}
2024-12-26 07:12:50 +00:00
2024-12-27 04:23:03 +00:00
await HandleAnswer ( answerMessage . Content , nextStep , interviewRoot , currentStep , answerMessage . Channel , answerMessage ) ;
2024-12-26 07:16:18 +00:00
return ;
}
2024-12-26 07:12:50 +00:00
2024-12-27 04:23:03 +00:00
Logger . Error ( "The interview for channel " + answerMessage . Channel . Id + " reached a step of type " + currentStep . messageType + " which has no valid next step. Their message was:\n" + answerMessage . Content ) ;
2024-12-26 07:32:34 +00:00
DiscordMessage errorMessage = await answerMessage . RespondAsync ( new DiscordEmbedBuilder
2024-12-26 07:30:56 +00:00
{
2024-12-26 10:27:36 +00:00
Description = "Error: Could not determine the next question based on your answer. Check your response and ask an admin to check the bot logs if this seems incorrect." ,
2024-12-26 07:30:56 +00:00
Color = DiscordColor . Red
} ) ;
2024-12-27 04:23:03 +00:00
currentStep . AddRelatedMessageIDs ( answerMessage . Id , errorMessage . Id ) ;
2024-12-26 12:54:28 +00:00
Database . SaveInterview ( answerMessage . Channel . Id , interviewRoot ) ;
2024-12-26 07:16:18 +00:00
}
2024-12-26 07:12:50 +00:00
2024-12-26 07:51:41 +00:00
private static async Task HandleAnswer ( string answer ,
2024-12-27 04:23:03 +00:00
InterviewStep nextStep ,
InterviewStep interviewRoot ,
InterviewStep previousStep ,
2024-12-26 07:16:18 +00:00
DiscordChannel channel ,
2024-12-26 07:28:39 +00:00
DiscordMessage answerMessage = null )
2024-12-26 07:16:18 +00:00
{
2024-12-26 11:38:35 +00:00
// The error message type should not alter anything about the interview.
2024-12-27 04:23:03 +00:00
if ( nextStep . messageType ! = MessageType . ERROR )
2024-12-26 07:16:18 +00:00
{
2024-12-27 04:23:03 +00:00
previousStep . answer = answer ;
2024-12-26 11:38:35 +00:00
2024-12-27 04:23:03 +00:00
// There is no message ID if the step is not a text input.
previousStep . answerID = answerMessage = = null ? 0 : answerMessage . Id ;
2024-12-26 07:28:39 +00:00
}
2024-12-26 07:12:50 +00:00
2024-12-27 04:23:03 +00:00
// Create next step, or finish the interview.
switch ( nextStep . messageType )
2024-12-26 07:16:18 +00:00
{
2024-12-27 04:23:03 +00:00
case MessageType . TEXT_INPUT :
case MessageType . BUTTONS :
case MessageType . TEXT_SELECTOR :
case MessageType . ROLE_SELECTOR :
case MessageType . USER_SELECTOR :
case MessageType . CHANNEL_SELECTOR :
case MessageType . MENTIONABLE_SELECTOR :
await SendNextMessage ( channel , nextStep ) ;
2024-12-26 07:16:18 +00:00
Database . SaveInterview ( channel . Id , interviewRoot ) ;
break ;
2024-12-27 04:23:03 +00:00
case MessageType . END_WITH_SUMMARY :
2024-12-26 07:16:18 +00:00
OrderedDictionary summaryFields = new OrderedDictionary ( ) ;
interviewRoot . GetSummary ( ref summaryFields ) ;
2024-12-26 07:12:50 +00:00
2024-12-26 07:16:18 +00:00
DiscordEmbedBuilder embed = new DiscordEmbedBuilder ( )
{
2024-12-27 04:23:03 +00:00
Color = Utilities . StringToColor ( nextStep . color ) ,
Title = nextStep . heading ,
Description = nextStep . message ,
2024-12-26 07:16:18 +00:00
} ;
2024-12-26 07:12:50 +00:00
2024-12-26 07:16:18 +00:00
foreach ( DictionaryEntry entry in summaryFields )
{
embed . AddField ( ( string ) entry . Key , ( string ) entry . Value ) ;
}
2024-12-26 07:12:50 +00:00
2024-12-26 07:16:18 +00:00
await channel . SendMessageAsync ( embed ) ;
2024-12-26 07:12:50 +00:00
2024-12-26 10:47:55 +00:00
if ( Config . deleteMessagesAfterSummary )
{
await DeletePreviousMessages ( interviewRoot , channel ) ;
}
2024-12-26 07:28:39 +00:00
if ( ! Database . TryDeleteInterview ( channel . Id ) )
2024-12-26 07:16:18 +00:00
{
2024-12-26 07:28:39 +00:00
Logger . Error ( "Could not delete interview from database. Channel ID: " + channel . Id ) ;
2024-12-26 07:16:18 +00:00
}
2024-12-26 07:28:39 +00:00
return ;
2024-12-27 04:23:03 +00:00
case MessageType . END_WITHOUT_SUMMARY :
2024-12-26 07:28:39 +00:00
await channel . SendMessageAsync ( new DiscordEmbedBuilder ( )
{
2024-12-27 04:23:03 +00:00
Color = Utilities . StringToColor ( nextStep . color ) ,
Title = nextStep . heading ,
Description = nextStep . message
2024-12-26 07:28:39 +00:00
} ) ;
2024-12-26 07:12:50 +00:00
2024-12-26 10:47:55 +00:00
if ( Config . deleteMessagesAfterNoSummary )
{
await DeletePreviousMessages ( interviewRoot , channel ) ;
}
2024-12-26 07:16:18 +00:00
if ( ! Database . TryDeleteInterview ( channel . Id ) )
{
Logger . Error ( "Could not delete interview from database. Channel ID: " + channel . Id ) ;
}
break ;
2024-12-27 04:23:03 +00:00
case MessageType . ERROR :
2024-12-26 07:16:18 +00:00
default :
2024-12-26 07:28:39 +00:00
if ( answerMessage = = null )
{
DiscordMessage errorMessage = await channel . SendMessageAsync ( new DiscordEmbedBuilder ( )
{
2024-12-27 04:23:03 +00:00
Color = Utilities . StringToColor ( nextStep . color ) ,
Title = nextStep . heading ,
Description = nextStep . message
2024-12-26 07:28:39 +00:00
} ) ;
2024-12-27 04:23:03 +00:00
previousStep . AddRelatedMessageIDs ( errorMessage . Id ) ;
2024-12-26 07:28:39 +00:00
}
else
{
DiscordMessageBuilder errorMessageBuilder = new DiscordMessageBuilder ( )
. AddEmbed ( new DiscordEmbedBuilder ( )
{
2024-12-27 04:23:03 +00:00
Color = Utilities . StringToColor ( nextStep . color ) ,
Title = nextStep . heading ,
Description = nextStep . message
2024-12-26 07:28:39 +00:00
} ) . WithReply ( answerMessage . Id ) ;
DiscordMessage errorMessage = await answerMessage . RespondAsync ( errorMessageBuilder ) ;
2024-12-27 04:23:03 +00:00
previousStep . AddRelatedMessageIDs ( errorMessage . Id , answerMessage . Id ) ;
2024-12-26 07:28:39 +00:00
}
2024-12-26 12:24:42 +00:00
Database . SaveInterview ( channel . Id , interviewRoot ) ;
2024-12-26 07:16:18 +00:00
break ;
}
2024-12-26 04:55:00 +00:00
}
2024-12-27 04:23:03 +00:00
private static async Task DeletePreviousMessages ( InterviewStep interviewRoot , DiscordChannel channel )
2024-12-26 07:28:39 +00:00
{
2024-12-26 11:38:35 +00:00
List < ulong > previousMessages = [ ] ;
2024-12-26 07:28:39 +00:00
interviewRoot . GetMessageIDs ( ref previousMessages ) ;
foreach ( ulong previousMessageID in previousMessages )
{
try
{
DiscordMessage previousMessage = await channel . GetMessageAsync ( previousMessageID ) ;
await channel . DeleteMessageAsync ( previousMessage , "Deleting old interview message." ) ;
}
catch ( Exception e )
{
Logger . Warn ( "Failed to delete old interview message: " , e ) ;
}
}
}
2024-12-27 04:23:03 +00:00
private static async Task SendNextMessage ( DiscordChannel channel , InterviewStep step )
2024-12-26 04:55:00 +00:00
{
2024-12-26 09:24:42 +00:00
DiscordMessageBuilder msgBuilder = new ( ) ;
DiscordEmbedBuilder embed = new ( )
2024-12-26 04:55:00 +00:00
{
2024-12-27 04:23:03 +00:00
Color = Utilities . StringToColor ( step . color ) ,
Title = step . heading ,
Description = step . message
2024-12-26 04:55:00 +00:00
} ;
2024-12-27 04:23:03 +00:00
switch ( step . messageType )
2024-12-26 04:55:00 +00:00
{
2024-12-27 04:23:03 +00:00
case MessageType . BUTTONS :
2024-12-26 04:55:00 +00:00
int nrOfButtons = 0 ;
2024-12-27 04:23:03 +00:00
for ( int nrOfButtonRows = 0 ; nrOfButtonRows < 5 & & nrOfButtons < step . steps . Count ; nrOfButtonRows + + )
2024-12-26 04:55:00 +00:00
{
List < DiscordButtonComponent > buttonRow = [ ] ;
2024-12-27 04:23:03 +00:00
for ( ; nrOfButtons < 5 * ( nrOfButtonRows + 1 ) & & nrOfButtons < step . steps . Count ; nrOfButtons + + )
2024-12-26 04:55:00 +00:00
{
2024-12-27 04:23:03 +00:00
( string stepPattern , InterviewStep nextStep ) = step . steps . ToArray ( ) [ nrOfButtons ] ;
buttonRow . Add ( new DiscordButtonComponent ( nextStep . GetButtonStyle ( ) , "supportchild_interviewbutton " + nrOfButtons , stepPattern ) ) ;
2024-12-26 04:55:00 +00:00
}
msgBuilder . AddComponents ( buttonRow ) ;
}
break ;
2024-12-27 04:23:03 +00:00
case MessageType . TEXT_SELECTOR :
2024-12-26 04:55:00 +00:00
List < DiscordSelectComponent > selectionComponents = [ ] ;
int selectionOptions = 0 ;
2024-12-27 04:23:03 +00:00
for ( int selectionBoxes = 0 ; selectionBoxes < 5 & & selectionOptions < step . steps . Count ; selectionBoxes + + )
2024-12-26 04:55:00 +00:00
{
List < DiscordSelectComponentOption > categoryOptions = [ ] ;
2024-12-27 04:23:03 +00:00
for ( ; selectionOptions < 25 * ( selectionBoxes + 1 ) & & selectionOptions < step . steps . Count ; selectionOptions + + )
2024-12-26 04:55:00 +00:00
{
2024-12-27 04:23:03 +00:00
( string stepPattern , InterviewStep nextStep ) = step . steps . ToArray ( ) [ selectionOptions ] ;
categoryOptions . Add ( new DiscordSelectComponentOption ( stepPattern , selectionOptions . ToString ( ) , nextStep . selectorDescription ) ) ;
2024-12-26 04:55:00 +00:00
}
2024-12-26 09:24:42 +00:00
2024-12-27 04:23:03 +00:00
selectionComponents . Add ( new DiscordSelectComponent ( "supportchild_interviewselector " + selectionBoxes , string . IsNullOrWhiteSpace ( step . selectorPlaceholder )
? "Select an option..." : step . selectorPlaceholder , categoryOptions ) ) ;
2024-12-26 04:55:00 +00:00
}
msgBuilder . AddComponents ( selectionComponents ) ;
break ;
2024-12-27 04:23:03 +00:00
case MessageType . ROLE_SELECTOR :
msgBuilder . AddComponents ( new DiscordRoleSelectComponent ( "supportchild_interviewroleselector" , string . IsNullOrWhiteSpace ( step . selectorPlaceholder )
? "Select a role..." : step . selectorPlaceholder ) ) ;
2024-12-26 07:51:41 +00:00
break ;
2024-12-27 04:23:03 +00:00
case MessageType . USER_SELECTOR :
msgBuilder . AddComponents ( new DiscordUserSelectComponent ( "supportchild_interviewuserselector" , string . IsNullOrWhiteSpace ( step . selectorPlaceholder )
? "Select a user..." : step . selectorPlaceholder ) ) ;
2024-12-26 07:51:41 +00:00
break ;
2024-12-27 04:23:03 +00:00
case MessageType . CHANNEL_SELECTOR :
msgBuilder . AddComponents ( new DiscordChannelSelectComponent ( "supportchild_interviewchannelselector" , string . IsNullOrWhiteSpace ( step . selectorPlaceholder )
? "Select a channel..." : step . selectorPlaceholder ) ) ;
2024-12-26 07:51:41 +00:00
break ;
2024-12-27 04:23:03 +00:00
case MessageType . MENTIONABLE_SELECTOR :
msgBuilder . AddComponents ( new DiscordMentionableSelectComponent ( "supportchild_interviewmentionableselector" , string . IsNullOrWhiteSpace ( step . selectorPlaceholder )
? "Select a user or role..." : step . selectorPlaceholder ) ) ;
2024-12-26 07:51:41 +00:00
break ;
2024-12-27 04:23:03 +00:00
case MessageType . TEXT_INPUT :
2024-12-26 07:12:50 +00:00
embed . WithFooter ( "Reply to this message with your answer. You cannot include images or files." ) ;
2024-12-26 04:55:00 +00:00
break ;
2024-12-27 04:23:03 +00:00
case MessageType . END_WITH_SUMMARY :
case MessageType . END_WITHOUT_SUMMARY :
case MessageType . ERROR :
2024-12-26 04:55:00 +00:00
default :
break ;
}
2024-12-26 05:07:36 +00:00
msgBuilder . AddEmbed ( embed ) ;
2024-12-26 04:55:00 +00:00
DiscordMessage message = await channel . SendMessageAsync ( msgBuilder ) ;
2024-12-27 04:23:03 +00:00
step . messageID = message . Id ;
2024-12-26 04:55:00 +00:00
}
}