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 03:43:55 +00:00
if ( ! Database . TryGetInterviewTemplate ( channel . Parent . Id , out InterviewQuestion 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 03:43:55 +00:00
await CreateQuestion ( channel , template ) ;
return Database . SaveInterview ( channel . Id , template ) ;
}
public static async Task < bool > RestartInterview ( DiscordChannel channel )
{
if ( Database . TryGetInterview ( channel . Id , out InterviewQuestion 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 03:43:55 +00:00
if ( Database . TryGetInterview ( channel . Id , out InterviewQuestion 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-26 10:33:32 +00:00
if ( ! Database . TryGetInterview ( interaction . Channel . Id , out InterviewQuestion 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-26 07:12:50 +00:00
if ( ! interviewRoot . TryGetCurrentQuestion ( out InterviewQuestion currentQuestion ) )
{
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 ( ) ) ;
Logger . Error ( "The interview for channel " + interaction . Channel . Id + " exists but does not have a message ID set for it's root question" ) ;
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-26 07:12:50 +00:00
if ( interaction . Message . Id ! = currentQuestion . messageID )
{
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-26 10:27:36 +00:00
foreach ( KeyValuePair < string , InterviewQuestion > path in currentQuestion . paths )
2024-12-26 07:51:41 +00:00
{
2024-12-26 10:27:36 +00:00
// Skip to the first matching path.
if ( Regex . IsMatch ( answer , path . Key ) )
{
await HandleAnswer ( answer , path . Value , interviewRoot , currentQuestion , interaction . Channel ) ;
return ;
}
2024-12-26 07:51:41 +00:00
}
2024-12-26 07:12:50 +00:00
2024-12-26 10:27:36 +00:00
Logger . Error ( "The interview for channel " + interaction . Channel . Id + " reached a question of type " + currentQuestion . type + " which has no valid next question. 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-26 12:54:28 +00:00
currentQuestion . AddRelatedMessageIDs ( followupMessage . Id ) ;
Database . SaveInterview ( interaction . Channel . Id , interviewRoot ) ;
2024-12-26 07:12:50 +00:00
}
2024-12-26 07:51:41 +00:00
else
{
if ( ! int . TryParse ( componentID , out int pathIndex ) )
{
Logger . Error ( "Invalid interview button/selector index: " + componentID ) ;
return ;
}
2024-12-26 07:12:50 +00:00
2024-12-26 07:51:41 +00:00
if ( pathIndex > = currentQuestion . paths . Count | | pathIndex < 0 )
{
Logger . Error ( "Invalid interview button/selector index: " + pathIndex ) ;
return ;
}
( string questionString , InterviewQuestion nextQuestion ) = currentQuestion . paths . ElementAt ( pathIndex ) ;
await HandleAnswer ( questionString , nextQuestion , interviewRoot , currentQuestion , interaction . Channel ) ;
}
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-26 10:33:32 +00:00
if ( ! Database . TryGetInterview ( answerMessage . ReferencedMessage . Channel . Id , out InterviewQuestion interviewRoot ) )
2024-12-26 07:12:50 +00:00
{
return ;
}
if ( ! interviewRoot . TryGetCurrentQuestion ( out InterviewQuestion currentQuestion ) )
{
return ;
}
// The user responded to something other than the latest interview question.
2024-12-26 07:32:34 +00:00
if ( answerMessage . ReferencedMessage . Id ! = currentQuestion . messageID )
2024-12-26 07:12:50 +00:00
{
return ;
}
// The user responded to a question which does not take a text response.
if ( currentQuestion . type ! = QuestionType . TEXT_INPUT )
{
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-26 12:54:28 +00:00
int maxLength = Math . Min ( currentQuestion . 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
} ) ;
currentQuestion . 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-26 12:54:28 +00:00
if ( answerMessage . Content . Length < ( currentQuestion . minLength ? ? 0 ) )
2024-12-26 07:32:34 +00:00
{
DiscordMessage lengthMessage = await answerMessage . RespondAsync ( new DiscordEmbedBuilder
{
Description = "Error: Your answer must be at least " + currentQuestion . minLength + " characters (" + answerMessage . Content . Length + "/" + currentQuestion . minLength + ")." ,
Color = DiscordColor . Red
} ) ;
currentQuestion . 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-26 07:12:50 +00:00
foreach ( ( string questionString , InterviewQuestion nextQuestion ) in currentQuestion . paths )
{
2024-12-26 07:30:56 +00:00
// Skip to the first matching path.
2024-12-26 12:54:28 +00:00
if ( ! Regex . IsMatch ( answerMessage . Content , questionString ) )
{
continue ;
}
2024-12-26 07:12:50 +00:00
2024-12-26 07:51:41 +00:00
await HandleAnswer ( answerMessage . Content , nextQuestion , interviewRoot , currentQuestion , answerMessage . Channel , answerMessage ) ;
2024-12-26 07:16:18 +00:00
return ;
}
2024-12-26 07:12:50 +00:00
2024-12-26 10:27:36 +00:00
Logger . Error ( "The interview for channel " + answerMessage . Channel . Id + " reached a question of type " + currentQuestion . type + " which has no valid next question. 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-26 12:54:28 +00:00
currentQuestion . AddRelatedMessageIDs ( answerMessage . Id , errorMessage . Id ) ;
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-26 07:16:18 +00:00
InterviewQuestion nextQuestion ,
InterviewQuestion interviewRoot ,
InterviewQuestion previousQuestion ,
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-26 07:28:39 +00:00
if ( nextQuestion . type ! = QuestionType . ERROR )
2024-12-26 07:16:18 +00:00
{
2024-12-26 07:51:41 +00:00
previousQuestion . answer = answer ;
2024-12-26 11:38:35 +00:00
// There is no message ID if the question is not a text input.
previousQuestion . answerID = answerMessage = = null ? 0 : answerMessage . Id ;
2024-12-26 07:28:39 +00:00
}
2024-12-26 07:12:50 +00:00
2024-12-26 07:16:18 +00:00
// Create next question, or finish the interview.
switch ( nextQuestion . type )
{
case QuestionType . TEXT_INPUT :
case QuestionType . BUTTONS :
case QuestionType . TEXT_SELECTOR :
2024-12-26 07:51:41 +00:00
case QuestionType . ROLE_SELECTOR :
case QuestionType . USER_SELECTOR :
case QuestionType . CHANNEL_SELECTOR :
case QuestionType . MENTIONABLE_SELECTOR :
2024-12-26 07:16:18 +00:00
await CreateQuestion ( channel , nextQuestion ) ;
Database . SaveInterview ( channel . Id , interviewRoot ) ;
break ;
2024-12-26 07:28:39 +00:00
case QuestionType . 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 ( )
{
Color = Utilities . StringToColor ( nextQuestion . color ) ,
2024-12-26 07:32:34 +00:00
Title = nextQuestion . title ,
2024-12-26 07:16:18 +00:00
Description = nextQuestion . message ,
} ;
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 ;
case QuestionType . END_WITHOUT_SUMMARY :
await channel . SendMessageAsync ( new DiscordEmbedBuilder ( )
{
Color = Utilities . StringToColor ( nextQuestion . color ) ,
2024-12-26 07:32:34 +00:00
Title = nextQuestion . title ,
2024-12-26 07:28:39 +00:00
Description = nextQuestion . message
} ) ;
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 ;
case QuestionType . ERROR :
default :
2024-12-26 07:28:39 +00:00
if ( answerMessage = = null )
{
DiscordMessage errorMessage = await channel . SendMessageAsync ( new DiscordEmbedBuilder ( )
{
Color = Utilities . StringToColor ( nextQuestion . color ) ,
2024-12-26 07:32:34 +00:00
Title = nextQuestion . title ,
2024-12-26 07:28:39 +00:00
Description = nextQuestion . message
} ) ;
previousQuestion . AddRelatedMessageIDs ( errorMessage . Id ) ;
}
else
{
DiscordMessageBuilder errorMessageBuilder = new DiscordMessageBuilder ( )
. AddEmbed ( new DiscordEmbedBuilder ( )
{
Color = Utilities . StringToColor ( nextQuestion . color ) ,
2024-12-26 07:32:34 +00:00
Title = nextQuestion . title ,
2024-12-26 07:28:39 +00:00
Description = nextQuestion . message
} ) . WithReply ( answerMessage . Id ) ;
DiscordMessage errorMessage = await answerMessage . RespondAsync ( errorMessageBuilder ) ;
previousQuestion . AddRelatedMessageIDs ( errorMessage . Id , answerMessage . Id ) ;
}
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-26 07:28:39 +00:00
private static async Task DeletePreviousMessages ( InterviewQuestion interviewRoot , DiscordChannel channel )
{
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-26 07:12:50 +00:00
private static async Task CreateQuestion ( DiscordChannel channel , InterviewQuestion question )
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-26 05:07:36 +00:00
Color = Utilities . StringToColor ( question . color ) ,
2024-12-26 07:32:34 +00:00
Title = question . title ,
2024-12-26 05:07:36 +00:00
Description = question . message
2024-12-26 04:55:00 +00:00
} ;
switch ( question . type )
{
case QuestionType . BUTTONS :
int nrOfButtons = 0 ;
for ( int nrOfButtonRows = 0 ; nrOfButtonRows < 5 & & nrOfButtons < question . paths . Count ; nrOfButtonRows + + )
{
List < DiscordButtonComponent > buttonRow = [ ] ;
for ( ; nrOfButtons < 5 * ( nrOfButtonRows + 1 ) & & nrOfButtons < question . paths . Count ; nrOfButtons + + )
{
2024-12-26 07:32:34 +00:00
( string questionString , InterviewQuestion nextQuestion ) = question . paths . ToArray ( ) [ nrOfButtons ] ;
buttonRow . Add ( new DiscordButtonComponent ( nextQuestion . GetButtonStyle ( ) , "supportchild_interviewbutton " + nrOfButtons , questionString ) ) ;
2024-12-26 04:55:00 +00:00
}
msgBuilder . AddComponents ( buttonRow ) ;
}
break ;
2024-12-26 07:16:18 +00:00
case QuestionType . TEXT_SELECTOR :
2024-12-26 04:55:00 +00:00
List < DiscordSelectComponent > selectionComponents = [ ] ;
int selectionOptions = 0 ;
for ( int selectionBoxes = 0 ; selectionBoxes < 5 & & selectionOptions < question . paths . Count ; selectionBoxes + + )
{
List < DiscordSelectComponentOption > categoryOptions = [ ] ;
for ( ; selectionOptions < 25 * ( selectionBoxes + 1 ) & & selectionOptions < question . paths . Count ; selectionOptions + + )
{
2024-12-26 10:25:11 +00:00
( string questionString , InterviewQuestion nextQuestion ) = question . paths . ToArray ( ) [ selectionOptions ] ;
categoryOptions . Add ( new DiscordSelectComponentOption ( questionString , selectionOptions . ToString ( ) , nextQuestion . selectorDescription ) ) ;
2024-12-26 04:55:00 +00:00
}
2024-12-26 09:24:42 +00:00
selectionComponents . Add ( new DiscordSelectComponent ( "supportchild_interviewselector " + selectionBoxes , string . IsNullOrWhiteSpace ( question . selectorPlaceholder )
? "Select an option..." : question . selectorPlaceholder , categoryOptions ) ) ;
2024-12-26 04:55:00 +00:00
}
msgBuilder . AddComponents ( selectionComponents ) ;
break ;
2024-12-26 07:51:41 +00:00
case QuestionType . ROLE_SELECTOR :
2024-12-26 09:24:42 +00:00
msgBuilder . AddComponents ( new DiscordRoleSelectComponent ( "supportchild_interviewroleselector" , string . IsNullOrWhiteSpace ( question . selectorPlaceholder )
? "Select a role..." : question . selectorPlaceholder ) ) ;
2024-12-26 07:51:41 +00:00
break ;
case QuestionType . USER_SELECTOR :
2024-12-26 09:24:42 +00:00
msgBuilder . AddComponents ( new DiscordUserSelectComponent ( "supportchild_interviewuserselector" , string . IsNullOrWhiteSpace ( question . selectorPlaceholder )
? "Select a user..." : question . selectorPlaceholder ) ) ;
2024-12-26 07:51:41 +00:00
break ;
case QuestionType . CHANNEL_SELECTOR :
2024-12-26 09:24:42 +00:00
msgBuilder . AddComponents ( new DiscordChannelSelectComponent ( "supportchild_interviewchannelselector" , string . IsNullOrWhiteSpace ( question . selectorPlaceholder )
? "Select a channel..." : question . selectorPlaceholder ) ) ;
2024-12-26 07:51:41 +00:00
break ;
case QuestionType . MENTIONABLE_SELECTOR :
2024-12-26 09:24:42 +00:00
msgBuilder . AddComponents ( new DiscordMentionableSelectComponent ( "supportchild_interviewmentionableselector" , string . IsNullOrWhiteSpace ( question . selectorPlaceholder )
? "Select a user or role..." : question . selectorPlaceholder ) ) ;
2024-12-26 07:51:41 +00:00
break ;
2024-12-26 04:55:00 +00:00
case QuestionType . 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-26 07:28:39 +00:00
case QuestionType . END_WITH_SUMMARY :
case QuestionType . END_WITHOUT_SUMMARY :
2024-12-26 07:18:07 +00:00
case QuestionType . 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 ) ;
question . messageID = message . Id ;
}
}