Get templates from database every time a new interview is started to avoid issues with the templates being passed by reference and then modified accidentally

This commit is contained in:
Toastie 2024-12-26 20:38:17 +13:00
parent 1ced350789
commit d9fcef449a
Signed by: toastie_t0ast
GPG key ID: 27F3B6855AFD40A4
4 changed files with 39 additions and 23 deletions

View file

@ -297,7 +297,6 @@ public class AdminCommands
}
Database.SetInterviewTemplates(JsonConvert.SerializeObject(interview, Formatting.Indented));
Interviewer.Reload();
}
catch (Exception e)
{

View file

@ -751,7 +751,8 @@ public static class Database
return templates;
}
public static Dictionary<ulong, Interviewer.InterviewQuestion> GetInterviewTemplates()
// Still returns true if there are no templates, returns false if the templates are invalid.
public static bool TryGetInterviewTemplates(out Dictionary<ulong, Interviewer.InterviewQuestion> templates)
{
using MySqlConnection c = GetConnection();
c.Open();
@ -762,21 +763,31 @@ public static class Database
// Check if messages exist in the database
if (!results.Read())
{
return new Dictionary<ulong, Interviewer.InterviewQuestion>();
templates = new Dictionary<ulong, Interviewer.InterviewQuestion>();
return true;
}
string templates = results.GetString("interview");
string templatesString = results.GetString("interview");
results.Close();
return JsonConvert.DeserializeObject<Dictionary<ulong, Interviewer.InterviewQuestion>>(templates, new JsonSerializerSettings
try
{
Error = delegate (object sender, ErrorEventArgs args)
templates = JsonConvert.DeserializeObject<Dictionary<ulong, Interviewer.InterviewQuestion>>(templatesString, new JsonSerializerSettings
{
Logger.Error("Error occured when trying to read interview templates from database: " + args.ErrorContext.Error.Message);
Logger.Debug("Detailed exception:", args.ErrorContext.Error);
args.ErrorContext.Handled = false;
}
});
Error = delegate (object sender, ErrorEventArgs args)
{
Logger.Error("Error occured when trying to read interview templates from database: " + args.ErrorContext.Error.Message);
Logger.Debug("Detailed exception:", args.ErrorContext.Error);
args.ErrorContext.Handled = false;
}
});
return true;
}
catch (Exception)
{
templates = null;
return false;
}
}
public static bool SetInterviewTemplates(string templates)
@ -833,7 +844,7 @@ public static class Database
}
catch (Exception e)
{
Logger.Error("Error occured when trying to read interview from database, it will not be loaded until manually fixed in the database.\nError message: " + e.Message);
Logger.Warn("Error occured when trying to read interview from database, it will not be loaded until manually fixed in the database.\nError message: " + e.Message);
Logger.Debug("Detailed exception:", e);
}

View file

@ -40,8 +40,6 @@ public static class Interviewer
// The entire interview tree is serialized and stored in the database in order to record responses as they are made.
public class InterviewQuestion
{
// TODO: Other selector types.
// Title of the message embed.
[JsonProperty("title")]
public string title;
@ -220,14 +218,10 @@ public static class Interviewer
public Dictionary<string, ValidatedInterviewQuestion> paths;
}
private static Dictionary<ulong, InterviewQuestion> interviewTemplates = [];
private static Dictionary<ulong, InterviewQuestion> activeInterviews = [];
// TODO: Maybe split into two functions?
public static void Reload()
public static void ReloadInterviews()
{
interviewTemplates = Database.GetInterviewTemplates();
activeInterviews = Database.GetAllInterviews();
}
@ -238,11 +232,22 @@ public static class Interviewer
return;
}
if (interviewTemplates.TryGetValue(channel.Parent.Id, out InterviewQuestion interview))
if (!Database.TryGetInterviewTemplates(out Dictionary<ulong, InterviewQuestion> templates))
{
await channel.SendMessageAsync(new DiscordEmbedBuilder
{
Description = "Attempted to create interview from template, but an error occured when reading it from the database.\n\n" +
"Tell a staff member to check the bot log and fix the template.",
Color = DiscordColor.Red
});
return;
}
if (templates.TryGetValue(channel.Parent.Id, out InterviewQuestion interview))
{
await CreateQuestion(channel, interview);
Database.SaveInterview(channel.Id, interview);
Reload();
activeInterviews = Database.GetAllInterviews();
}
}
@ -462,7 +467,7 @@ public static class Interviewer
{
Logger.Error("Could not delete interview from database. Channel ID: " + channel.Id);
}
Reload();
ReloadInterviews();
return;
case QuestionType.END_WITHOUT_SUMMARY:
// TODO: Add command to restart interview.
@ -478,7 +483,7 @@ public static class Interviewer
{
Logger.Error("Could not delete interview from database. Channel ID: " + channel.Id);
}
Reload();
ReloadInterviews();
break;
case QuestionType.ERROR:
default:

View file

@ -152,6 +152,7 @@ internal static class SupportChild
try
{
Logger.Log("Loading interviews from database...");
Interviewer.ReloadInterviews();
}
catch (Exception e)
{