Made it possible to add a summary to any message instead of only interview ends
This commit is contained in:
parent
abe0e3397e
commit
d8e1863182
5 changed files with 75 additions and 88 deletions
|
@ -28,8 +28,7 @@ internal static class Config
|
|||
internal static bool closingNotifications = false;
|
||||
|
||||
internal static bool interviewsEnabled = false;
|
||||
internal static bool deleteMessagesAfterSummary = false;
|
||||
internal static bool deleteMessagesAfterNoSummary = false;
|
||||
internal static bool deleteMessagesAfterInterviewEnd = false;
|
||||
|
||||
internal static string hostName = "127.0.0.1";
|
||||
internal static int port = 3306;
|
||||
|
@ -100,8 +99,7 @@ internal static class Config
|
|||
closingNotifications = json.SelectToken("notifications.closing")?.Value<bool>() ?? false;
|
||||
|
||||
interviewsEnabled = json.SelectToken("interviews.enabled")?.Value<bool>() ?? false;
|
||||
deleteMessagesAfterSummary = json.SelectToken("interviews.delete-messages-after-summary")?.Value<bool>() ?? false;
|
||||
deleteMessagesAfterNoSummary = json.SelectToken("interviews.delete-messages-after-no-summary")?.Value<bool>() ?? false;
|
||||
deleteMessagesAfterInterviewEnd = json.SelectToken("interviews.delete-messages-after-interview-end")?.Value<bool>() ?? false;
|
||||
|
||||
// Reads database info
|
||||
hostName = json.SelectToken("database.address")?.Value<string>() ?? "";
|
||||
|
|
|
@ -15,8 +15,9 @@ public enum MessageType
|
|||
{
|
||||
// TODO: Support multiselector as separate type
|
||||
ERROR,
|
||||
END_WITH_SUMMARY,
|
||||
END_WITHOUT_SUMMARY,
|
||||
INTERVIEW_END = 1,
|
||||
[Obsolete("Use INTERVIEW_END instead")] END_WITH_SUMMARY = 1,
|
||||
[Obsolete("Use INTERVIEW_END instead")] END_WITHOUT_SUMMARY = 1,
|
||||
BUTTONS,
|
||||
TEXT_SELECTOR,
|
||||
USER_SELECTOR,
|
||||
|
@ -125,6 +126,10 @@ public class InterviewStep
|
|||
[JsonProperty("min-length")]
|
||||
public int? minLength;
|
||||
|
||||
// Adds a summary to the message.
|
||||
[JsonProperty("add-summary")]
|
||||
public bool? addSummary;
|
||||
|
||||
// References to steps defined elsewhere in the template
|
||||
[JsonProperty("step-references")]
|
||||
public Dictionary<string, ReferencedInterviewStep> references = new();
|
||||
|
@ -185,7 +190,7 @@ public class InterviewStep
|
|||
}
|
||||
|
||||
// This object is the deepest object with a message ID set, meaning it is the latest asked question.
|
||||
previousSteps = new List<InterviewStep> { this };
|
||||
previousSteps = [this];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -196,7 +201,7 @@ public class InterviewStep
|
|||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(summaryField))
|
||||
if (!string.IsNullOrWhiteSpace(summaryField) && !string.IsNullOrWhiteSpace(answer))
|
||||
{
|
||||
// TODO: Add option to merge answers
|
||||
summary[summaryField] = answer;
|
||||
|
@ -292,8 +297,7 @@ public class InterviewStep
|
|||
case MessageType.TEXT_INPUT:
|
||||
summaryMaxLength += Math.Min(maxLength ?? 1024, 1024);
|
||||
break;
|
||||
case MessageType.END_WITH_SUMMARY:
|
||||
case MessageType.END_WITHOUT_SUMMARY:
|
||||
case MessageType.INTERVIEW_END:
|
||||
case MessageType.ERROR:
|
||||
case MessageType.REFERENCE_END:
|
||||
default:
|
||||
|
@ -317,7 +321,7 @@ public class InterviewStep
|
|||
}
|
||||
}
|
||||
|
||||
if (messageType is MessageType.ERROR or MessageType.END_WITH_SUMMARY or MessageType.END_WITHOUT_SUMMARY or MessageType.REFERENCE_END)
|
||||
if (messageType is MessageType.ERROR or MessageType.INTERVIEW_END or MessageType.REFERENCE_END)
|
||||
{
|
||||
if (steps.Count > 0 || references.Count > 0)
|
||||
{
|
||||
|
@ -334,7 +338,6 @@ public class InterviewStep
|
|||
errors.Add("Steps of the type '" + messageType + "' must have at least one child step.\n\n> " + stepID + ".message-type");
|
||||
}
|
||||
|
||||
// TODO: Test this
|
||||
foreach (KeyValuePair<string, ReferencedInterviewStep> reference in references)
|
||||
{
|
||||
if (!reference.Value.TryGetReferencedStep(definitions, out InterviewStep referencedStep, true))
|
||||
|
@ -343,7 +346,7 @@ public class InterviewStep
|
|||
}
|
||||
else if (reference.Value.afterReferenceStep == null)
|
||||
{
|
||||
List<InterviewStep> allChildSteps = new List<InterviewStep>();
|
||||
List<InterviewStep> allChildSteps = [];
|
||||
referencedStep.GetAllSteps(ref allChildSteps);
|
||||
if (allChildSteps.Any(s => s.messageType == MessageType.REFERENCE_END))
|
||||
{
|
||||
|
@ -352,7 +355,7 @@ public class InterviewStep
|
|||
}
|
||||
}
|
||||
|
||||
if (messageType is MessageType.END_WITH_SUMMARY)
|
||||
if (addSummary ?? false)
|
||||
{
|
||||
summaryMaxLength += message?.Length ?? 0;
|
||||
summaryMaxLength += heading?.Length ?? 0;
|
||||
|
|
|
@ -19,7 +19,7 @@ public static class Interviewer
|
|||
return false;
|
||||
}
|
||||
|
||||
await SendNextMessage(channel, interview.interviewRoot);
|
||||
await SendNextMessage(interview, channel, interview.interviewRoot);
|
||||
return Database.SaveInterview(interview);
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ public static class Interviewer
|
|||
{
|
||||
if (Database.TryGetInterview(channel.Id, out Interview interview))
|
||||
{
|
||||
if (Config.deleteMessagesAfterNoSummary)
|
||||
if (Config.deleteMessagesAfterInterviewEnd)
|
||||
{
|
||||
await DeletePreviousMessages(interview, channel);
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ public static class Interviewer
|
|||
{
|
||||
if (Database.TryGetInterview(channel.Id, out Interview interview))
|
||||
{
|
||||
if (Config.deleteMessagesAfterNoSummary)
|
||||
if (Config.deleteMessagesAfterInterviewEnd)
|
||||
{
|
||||
await DeletePreviousMessages(interview, channel);
|
||||
}
|
||||
|
@ -362,28 +362,25 @@ public static class Interviewer
|
|||
}
|
||||
nextStep.references.Clear();
|
||||
|
||||
await SendNextMessage(channel, nextStep);
|
||||
await SendNextMessage(interview, channel, nextStep);
|
||||
Database.SaveInterview(interview);
|
||||
break;
|
||||
case MessageType.END_WITH_SUMMARY:
|
||||
OrderedDictionary summaryFields = new OrderedDictionary();
|
||||
interview.interviewRoot.GetSummary(ref summaryFields);
|
||||
|
||||
DiscordEmbedBuilder embed = new DiscordEmbedBuilder
|
||||
case MessageType.INTERVIEW_END:
|
||||
DiscordEmbedBuilder endEmbed = new()
|
||||
{
|
||||
Color = Utilities.StringToColor(nextStep.color),
|
||||
Title = nextStep.heading,
|
||||
Description = nextStep.message,
|
||||
};
|
||||
|
||||
foreach (DictionaryEntry entry in summaryFields)
|
||||
if (nextStep.addSummary ?? false)
|
||||
{
|
||||
embed.AddField((string)entry.Key, (string)entry.Value ?? string.Empty);
|
||||
AddSummary(interview, ref endEmbed);
|
||||
}
|
||||
|
||||
await channel.SendMessageAsync(embed);
|
||||
await channel.SendMessageAsync(endEmbed);
|
||||
|
||||
if (Config.deleteMessagesAfterSummary)
|
||||
if (Config.deleteMessagesAfterInterviewEnd)
|
||||
{
|
||||
await DeletePreviousMessages(interview, channel);
|
||||
}
|
||||
|
@ -393,26 +390,7 @@ public static class Interviewer
|
|||
Logger.Error("Could not delete interview from database. Channel ID: " + channel.Id);
|
||||
}
|
||||
return;
|
||||
case MessageType.END_WITHOUT_SUMMARY:
|
||||
await channel.SendMessageAsync(new DiscordEmbedBuilder
|
||||
{
|
||||
Color = Utilities.StringToColor(nextStep.color),
|
||||
Title = nextStep.heading,
|
||||
Description = nextStep.message
|
||||
});
|
||||
|
||||
if (Config.deleteMessagesAfterNoSummary)
|
||||
{
|
||||
await DeletePreviousMessages(interview, channel);
|
||||
}
|
||||
|
||||
if (!Database.TryDeleteInterview(channel.Id))
|
||||
{
|
||||
Logger.Error("Could not delete interview from database. Channel ID: " + channel.Id);
|
||||
}
|
||||
break;
|
||||
case MessageType.REFERENCE_END:
|
||||
// TODO: What is happening with the summaries?
|
||||
if (interview.interviewRoot.TryGetTakenSteps(out List<InterviewStep> previousSteps))
|
||||
{
|
||||
foreach (InterviewStep step in previousSteps)
|
||||
|
@ -431,19 +409,14 @@ public static class Interviewer
|
|||
|
||||
previousStep.steps.Clear();
|
||||
previousStep.steps.Add(answer, nextStep);
|
||||
await HandleAnswer(answer,
|
||||
nextStep,
|
||||
interview,
|
||||
previousStep,
|
||||
channel,
|
||||
answerMessage);
|
||||
await HandleAnswer(answer, nextStep, interview, previousStep, channel, answerMessage);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DiscordEmbedBuilder error = new DiscordEmbedBuilder
|
||||
DiscordEmbedBuilder error = new()
|
||||
{
|
||||
Color = DiscordColor.Red,
|
||||
Description = "An error occured while trying to find the next interview step."
|
||||
|
@ -466,26 +439,41 @@ public static class Interviewer
|
|||
return;
|
||||
case MessageType.ERROR:
|
||||
default:
|
||||
DiscordEmbedBuilder err = new DiscordEmbedBuilder
|
||||
DiscordEmbedBuilder errorEmbed = new()
|
||||
{
|
||||
Color = Utilities.StringToColor(nextStep.color),
|
||||
Title = nextStep.heading,
|
||||
Description = nextStep.message
|
||||
};
|
||||
|
||||
if (nextStep.addSummary ?? false)
|
||||
{
|
||||
AddSummary(interview, ref errorEmbed);
|
||||
}
|
||||
|
||||
if (answerMessage == null)
|
||||
{
|
||||
DiscordMessage errorMessage = await channel.SendMessageAsync(err);
|
||||
DiscordMessage errorMessage = await channel.SendMessageAsync(errorEmbed);
|
||||
previousStep.AddRelatedMessageIDs(errorMessage.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
DiscordMessage errorMessage = await answerMessage.RespondAsync(err);
|
||||
DiscordMessage errorMessage = await answerMessage.RespondAsync(errorEmbed);
|
||||
previousStep.AddRelatedMessageIDs(errorMessage.Id, answerMessage.Id);
|
||||
}
|
||||
|
||||
Database.SaveInterview(interview);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddSummary(Interview interview, ref DiscordEmbedBuilder embed)
|
||||
{
|
||||
OrderedDictionary summaryFields = new();
|
||||
interview.interviewRoot.GetSummary(ref summaryFields);
|
||||
foreach (DictionaryEntry entry in summaryFields)
|
||||
{
|
||||
embed.AddField((string)entry.Key, (string)entry.Value ?? "-");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -508,7 +496,7 @@ public static class Interviewer
|
|||
}
|
||||
}
|
||||
|
||||
private static async Task SendNextMessage(DiscordChannel channel, InterviewStep step)
|
||||
private static async Task SendNextMessage(Interview interview, DiscordChannel channel, InterviewStep step)
|
||||
{
|
||||
DiscordMessageBuilder msgBuilder = new();
|
||||
DiscordEmbedBuilder embed = new()
|
||||
|
@ -518,6 +506,11 @@ public static class Interviewer
|
|||
Description = step.message
|
||||
};
|
||||
|
||||
if (step.addSummary ?? false)
|
||||
{
|
||||
AddSummary(interview, ref embed);
|
||||
}
|
||||
|
||||
switch (step.messageType)
|
||||
{
|
||||
case MessageType.BUTTONS:
|
||||
|
@ -546,33 +539,32 @@ public static class Interviewer
|
|||
categoryOptions.Add(new DiscordSelectComponentOption(stepPattern, selectionOptions.ToString(), nextStep.selectorDescription));
|
||||
}
|
||||
|
||||
selectionComponents.Add(new DiscordSelectComponent("supportboi_interviewselector " + selectionBoxes, string.IsNullOrWhiteSpace(step.selectorPlaceholder)
|
||||
? "Select an option..." : step.selectorPlaceholder, categoryOptions));
|
||||
selectionComponents.Add(new DiscordSelectComponent("supportboi_interviewselector " + selectionBoxes,
|
||||
string.IsNullOrWhiteSpace(step.selectorPlaceholder) ? "Select an option..." : step.selectorPlaceholder, categoryOptions));
|
||||
}
|
||||
|
||||
msgBuilder.AddComponents(selectionComponents);
|
||||
break;
|
||||
case MessageType.ROLE_SELECTOR:
|
||||
msgBuilder.AddComponents(new DiscordRoleSelectComponent("supportboi_interviewroleselector", string.IsNullOrWhiteSpace(step.selectorPlaceholder)
|
||||
? "Select a role..." : step.selectorPlaceholder));
|
||||
msgBuilder.AddComponents(new DiscordRoleSelectComponent("supportboi_interviewroleselector",
|
||||
string.IsNullOrWhiteSpace(step.selectorPlaceholder) ? "Select a role..." : step.selectorPlaceholder));
|
||||
break;
|
||||
case MessageType.USER_SELECTOR:
|
||||
msgBuilder.AddComponents(new DiscordUserSelectComponent("supportboi_interviewuserselector", string.IsNullOrWhiteSpace(step.selectorPlaceholder)
|
||||
? "Select a user..." : step.selectorPlaceholder));
|
||||
msgBuilder.AddComponents(new DiscordUserSelectComponent("supportboi_interviewuserselector",
|
||||
string.IsNullOrWhiteSpace(step.selectorPlaceholder) ? "Select a user..." : step.selectorPlaceholder));
|
||||
break;
|
||||
case MessageType.CHANNEL_SELECTOR:
|
||||
msgBuilder.AddComponents(new DiscordChannelSelectComponent("supportboi_interviewchannelselector", string.IsNullOrWhiteSpace(step.selectorPlaceholder)
|
||||
? "Select a channel..." : step.selectorPlaceholder));
|
||||
msgBuilder.AddComponents(new DiscordChannelSelectComponent("supportboi_interviewchannelselector",
|
||||
string.IsNullOrWhiteSpace(step.selectorPlaceholder) ? "Select a channel..." : step.selectorPlaceholder));
|
||||
break;
|
||||
case MessageType.MENTIONABLE_SELECTOR:
|
||||
msgBuilder.AddComponents(new DiscordMentionableSelectComponent("supportboi_interviewmentionableselector", string.IsNullOrWhiteSpace(step.selectorPlaceholder)
|
||||
? "Select a user or role..." : step.selectorPlaceholder));
|
||||
msgBuilder.AddComponents(new DiscordMentionableSelectComponent("supportboi_interviewmentionableselector",
|
||||
string.IsNullOrWhiteSpace(step.selectorPlaceholder) ? "Select a user or role..." : step.selectorPlaceholder));
|
||||
break;
|
||||
case MessageType.TEXT_INPUT:
|
||||
embed.WithFooter("Reply to this message with your answer. You cannot include images or files.");
|
||||
break;
|
||||
case MessageType.END_WITH_SUMMARY:
|
||||
case MessageType.END_WITHOUT_SUMMARY:
|
||||
case MessageType.INTERVIEW_END:
|
||||
case MessageType.ERROR:
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -39,9 +39,7 @@
|
|||
"$ref": "#/definitions/step"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id"
|
||||
],
|
||||
"required": [ "id" ],
|
||||
"unevaluatedProperties": false
|
||||
},
|
||||
"step": {
|
||||
|
@ -58,7 +56,7 @@
|
|||
"message": {
|
||||
"type": "string",
|
||||
"title": "Message",
|
||||
"description": "The text in the embed message that will be sent to the user when they reach this step.",
|
||||
"description": "The text in the embed message that will be sent to the user when they reach this step. Required for all message types except 'REFERENCE_END'.",
|
||||
"minLength": 1
|
||||
},
|
||||
"message-type": {
|
||||
|
@ -67,8 +65,7 @@
|
|||
"description": "The type of message, decides what the bot will do when the user gets to this step.",
|
||||
"enum": [
|
||||
"ERROR",
|
||||
"END_WITH_SUMMARY",
|
||||
"END_WITHOUT_SUMMARY",
|
||||
"INTERVIEW_END",
|
||||
"BUTTONS",
|
||||
"TEXT_SELECTOR",
|
||||
"USER_SELECTOR",
|
||||
|
@ -189,11 +186,14 @@
|
|||
"title": "Min Length",
|
||||
"description": "The minimum length of the user's response message. Requires that this step is a 'TEXT_INPUT'.",
|
||||
"minimum": 0
|
||||
},
|
||||
"add-summary": {
|
||||
"type": "boolean",
|
||||
"title": "Add Summary",
|
||||
"description": "This adds a summary field to the end of the message."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"message-type"
|
||||
],
|
||||
"required": [ "message-type" ],
|
||||
"unevaluatedProperties": false
|
||||
}
|
||||
},
|
||||
|
@ -218,9 +218,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"category-id",
|
||||
"interview"
|
||||
],
|
||||
"required": [ "category-id", "interview" ],
|
||||
"unevaluatedProperties": false
|
||||
}
|
|
@ -61,11 +61,8 @@ interviews:
|
|||
# Any existing interviews can still be completed while interviews are disabled, but new ones will not be created.
|
||||
enabled: true
|
||||
|
||||
# Whether to delete the interview question and answer messages after an interview summary is posted.
|
||||
delete-messages-after-summary: true
|
||||
|
||||
# Whether to delete the interview question and answer messages after an interview ends without a summary.
|
||||
delete-messages-after-no-summary: true
|
||||
# Whether to delete the interview question and answer messages after an interview ends.
|
||||
delete-messages-after-interview-end: true
|
||||
|
||||
database:
|
||||
# Address and port of the mysql server.
|
||||
|
|
Loading…
Add table
Reference in a new issue