2024-12-26 04:55:00 +00:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using DSharpPlus;
|
|
|
|
|
using DSharpPlus.Entities;
|
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
|
|
|
|
|
|
namespace SupportChild;
|
|
|
|
|
|
|
|
|
|
public static class Interviewer
|
|
|
|
|
{
|
|
|
|
|
public enum QuestionType
|
|
|
|
|
{
|
|
|
|
|
DONE,
|
|
|
|
|
FAIL,
|
|
|
|
|
BUTTONS,
|
|
|
|
|
SELECTOR,
|
|
|
|
|
TEXT_INPUT
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// A tree of questions representing an interview.
|
|
|
|
|
// The tree is generated by the config file when a new ticket is opened or the restart interview command is used.
|
|
|
|
|
// Additional components not specified in the config file are populated as the interview progresses.
|
|
|
|
|
// The entire interview tree is serialized and stored in the database in order to record responses as they are made.
|
2024-12-26 05:07:36 +00:00
|
|
|
|
public class InterviewQuestion
|
2024-12-26 04:55:00 +00:00
|
|
|
|
{
|
|
|
|
|
// Message contents sent to the user.
|
|
|
|
|
public string message;
|
|
|
|
|
|
|
|
|
|
// The type of question.
|
|
|
|
|
public QuestionType type;
|
|
|
|
|
|
|
|
|
|
// Colour of the message embed.
|
|
|
|
|
public string color;
|
|
|
|
|
|
|
|
|
|
// The ID of this message, populated after it has been sent.
|
|
|
|
|
public ulong messageID;
|
|
|
|
|
|
|
|
|
|
// Used as label for this question in the post-interview summary.
|
|
|
|
|
public string summaryField;
|
|
|
|
|
|
|
|
|
|
// The user's response to the question.
|
|
|
|
|
public string answer;
|
|
|
|
|
|
|
|
|
|
// The ID of the user's answer message, populated after it has been received.
|
|
|
|
|
public ulong answerID;
|
|
|
|
|
|
|
|
|
|
// Possible questions to ask next, or DONE/FAIL type in order to finish interview.
|
|
|
|
|
public Dictionary<string, InterviewQuestion> paths;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static Dictionary<ulong, InterviewQuestion> categoryInterviews = [];
|
|
|
|
|
|
2024-12-26 05:07:36 +00:00
|
|
|
|
private static Dictionary<ulong, InterviewQuestion> activeInterviews = [];
|
|
|
|
|
|
2024-12-26 04:55:00 +00:00
|
|
|
|
public static void ParseConfig(JToken interviewConfig)
|
|
|
|
|
{
|
|
|
|
|
categoryInterviews = JsonConvert.DeserializeObject<Dictionary<ulong, InterviewQuestion>>(interviewConfig.ToString());
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-26 05:07:36 +00:00
|
|
|
|
public static void LoadActiveInterviews()
|
|
|
|
|
{
|
|
|
|
|
activeInterviews = Database.GetAllInterviews();
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-26 04:55:00 +00:00
|
|
|
|
public static void StartInterview(DiscordChannel channel)
|
|
|
|
|
{
|
|
|
|
|
if (channel.Parent == null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (categoryInterviews.TryGetValue(channel.Parent.Id, out InterviewQuestion interview))
|
|
|
|
|
{
|
|
|
|
|
CreateQuestion(channel, interview);
|
2024-12-26 05:07:36 +00:00
|
|
|
|
Database.SaveInterview(channel.Id, interview);
|
2024-12-26 04:55:00 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-26 05:07:36 +00:00
|
|
|
|
public static void ProcessResponse(DiscordMessage message)
|
2024-12-26 04:55:00 +00:00
|
|
|
|
{
|
2024-12-26 05:07:36 +00:00
|
|
|
|
// TODO: Find if channel has open interview.
|
|
|
|
|
// TODO: Find if message is replying to interview message.
|
|
|
|
|
// TODO: Handle other interactions like button presses.
|
|
|
|
|
// TODO: Find out where in the interview tree we are.
|
|
|
|
|
// TODO: Handle FAIL event, cancelling the interview.
|
|
|
|
|
// TODO: Handle DONE event, creating a summary.
|
|
|
|
|
|
|
|
|
|
//Database.SaveInterview(channel.Id, interview);
|
2024-12-26 04:55:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static async void CreateQuestion(DiscordChannel channel, InterviewQuestion question)
|
|
|
|
|
{
|
2024-12-26 05:07:36 +00:00
|
|
|
|
DiscordMessageBuilder msgBuilder = new DiscordMessageBuilder();
|
|
|
|
|
DiscordEmbedBuilder embed = new DiscordEmbedBuilder()
|
2024-12-26 04:55:00 +00:00
|
|
|
|
{
|
2024-12-26 05:07:36 +00:00
|
|
|
|
Color = Utilities.StringToColor(question.color),
|
|
|
|
|
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 05:07:36 +00:00
|
|
|
|
buttonRow.Add(new DiscordButtonComponent(ButtonStyle.Primary, "supportchild_interviewbutton " + nrOfButtons, question.paths.ToArray()[nrOfButtons].Key));
|
2024-12-26 04:55:00 +00:00
|
|
|
|
}
|
|
|
|
|
msgBuilder.AddComponents(buttonRow);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case QuestionType.SELECTOR:
|
|
|
|
|
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++)
|
|
|
|
|
{
|
|
|
|
|
categoryOptions.Add(new DiscordSelectComponentOption(question.paths.ToArray()[selectionOptions].Key, selectionOptions.ToString()));
|
|
|
|
|
}
|
2024-12-26 05:07:36 +00:00
|
|
|
|
selectionComponents.Add(new DiscordSelectComponent("supportchild_interviewselector " + selectionBoxes, "Select an option...", categoryOptions, false, 0, 1));
|
2024-12-26 04:55:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
msgBuilder.AddComponents(selectionComponents);
|
|
|
|
|
break;
|
|
|
|
|
case QuestionType.TEXT_INPUT:
|
2024-12-26 05:07:36 +00:00
|
|
|
|
embed.WithFooter("Reply to this message with your answer.");
|
2024-12-26 04:55:00 +00:00
|
|
|
|
break;
|
|
|
|
|
case QuestionType.DONE:
|
|
|
|
|
case QuestionType.FAIL:
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void CreateSummary()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|