public override void ExecuteCommand(EvtChatCommandArgs args) { List <string> arguments = args.Command.ArgumentsAsList; if (arguments.Count != 1) { QueueMessage(UsageMessage); return; } string macroName = arguments[0].ToLowerInvariant(); using (BotDBContext context = DatabaseManager.OpenContext()) { InputMacro macro = context.Macros.FirstOrDefault(m => m.MacroName == macroName); if (macro == null) { QueueMessage($"Input macro \"{macroName}\" could not be found."); return; } context.Macros.Remove(macro); context.SaveChanges(); } QueueMessage($"Removed input macro \"{macroName}\"."); }
public override void ExecuteCommand(EvtChatCommandArgs args) { List <string> arguments = args.Command.ArgumentsAsList; if (arguments.Count != 1) { QueueMessage(UsageMessage); return; } string macroName = arguments[0].ToLowerInvariant(); string message = string.Empty; using (BotDBContext context = DatabaseManager.OpenContext()) { InputMacro macro = context.Macros.FirstOrDefault(m => m.MacroName == macroName); if (macro == null) { message = $"Input macro \"{macroName}\" not found. For dynamic input macros, use the generic form (Ex. \"#test(*)\")."; } else { message = $"{macro.MacroName} = {macro.MacroValue}"; } } QueueMessage(message); }
private static void AddOldBotDataToNewDB(BotData oldBotData) { /* Macros */ Console.WriteLine("Begin importing macros..."); int macroCount = 0; foreach (KeyValuePair <string, string> macros in oldBotData.Macros) { Console.WriteLine($"Importing macro \"{macros.Key}\" to new data."); using (BotDBContext context = DatabaseManager.OpenContext()) { InputMacro newMacro = context.Macros.FirstOrDefault(m => m.MacroName == macros.Key); if (newMacro == null) { newMacro = new InputMacro(); context.Macros.Add(newMacro); } newMacro.MacroName = macros.Key; newMacro.MacroValue = macros.Value; context.SaveChanges(); } macroCount++; } Console.WriteLine($"Completed importing {macroCount} macros!"); /* Memes */ Console.WriteLine("Begin importing memes..."); int memeCount = 0; foreach (KeyValuePair <string, string> memes in oldBotData.Memes) { Console.WriteLine($"Importing meme \"{memes.Key}\" to new data."); using (BotDBContext context = DatabaseManager.OpenContext()) { Meme newMeme = context.Memes.FirstOrDefault(m => m.MemeName == memes.Key); if (newMeme == null) { newMeme = new Meme(); context.Memes.Add(newMeme); } newMeme.MemeName = memes.Key; newMeme.MemeValue = memes.Value; context.SaveChanges(); } memeCount++; } Console.WriteLine($"Completed importing {memeCount} memes!"); /* Users */ Console.WriteLine("Begin importing user data..."); int userCount = 0; //Migrate users foreach (KeyValuePair <string, TRBotDataMigrationTool.User> oldUser in oldBotData.Users) { string oldUserName = oldUser.Key; TRBotDataMigrationTool.User oldUserObj = oldUser.Value; Console.WriteLine($"Importing user \"{oldUserName}\" to new data."); using (BotDBContext context = DatabaseManager.OpenContext()) { TRBot.Data.User newUser = DataHelper.GetUserNoOpen(oldUserName, context); if (newUser == null) { newUser = new TRBot.Data.User(oldUserName); context.Users.Add(newUser); //Save changes here so the navigation properties are applied context.SaveChanges(); } //Migrate the user data MigrateUserFromOldToNew(oldUserObj, newUser); context.SaveChanges(); } //Update user abilities DataHelper.UpdateUserAutoGrantAbilities(oldUserName); userCount++; } Console.WriteLine($"Completed importing {userCount} users!"); /* Game Logs */ Console.WriteLine("Begin importing game logs..."); int logCount = 0; foreach (TRBotDataMigrationTool.GameLog log in oldBotData.Logs) { //The DateTime in the old logs were not standardized, so we have to parse them manually int separatorLength = DATETIME_AT_PARSE.Length; if (string.IsNullOrEmpty(log.DateTimeString) == true) { continue; } int middleIndex = log.DateTimeString.IndexOf(DATETIME_AT_PARSE); if (middleIndex < 0) { continue; } //Parse date string date = log.DateTimeString.Substring(0, middleIndex + 1); int.TryParse(date.Substring(0, 2), out int month); int.TryParse(date.Substring(3, 2), out int day); int.TryParse(date.Substring(6, 4), out int year); int endIndex = middleIndex + separatorLength; //Parse time string time = log.DateTimeString.Substring(endIndex, log.DateTimeString.Length - endIndex); int.TryParse(time.Substring(0, 2), out int hour); int.TryParse(time.Substring(3, 2), out int minute); int.TryParse(time.Substring(6, 2), out int seconds); DateTime newDateTime = new DateTime(year, month, day, hour, minute, seconds); TRBot.Data.GameLog newLog = new TRBot.Data.GameLog(); newLog.LogDateTime = newDateTime; newLog.LogMessage = log.LogMessage; newLog.User = log.User; using (BotDBContext context = DatabaseManager.OpenContext()) { context.GameLogs.Add(newLog); context.SaveChanges(); } logCount++; } Console.WriteLine($"Completed importing {logCount} game logs!"); /* Savestate Logs */ Console.WriteLine("Skipping importing savestate logs, as they don't exist in TRBot 2.0+."); /* Silenced Users */ Console.WriteLine($"Skipping importing silenced users, as TRBot 2.0+ has a new ability system (see the \"{TRBot.Permissions.PermissionConstants.SILENCED_ABILITY}\" ability)."); /* Input Callbacks */ Console.WriteLine("Skipping importing input callbacks, as they don't exist in TRBot 2.0+."); /* Input Access */ Console.WriteLine("Skipping importing InputAccess, as input access is console-specific in TRBot 2.0+."); /* Invalid Button Combos */ Console.WriteLine("Begin importing invalid button combos..."); int invalidButtonCombos = 0; foreach (KeyValuePair <int, List <string> > kvPair in oldBotData.InvalidBtnCombos.InvalidCombos) { int oldConsoleId = kvPair.Key; List <string> invalidCombos = kvPair.Value; if (EnumUtility.TryParseEnumValue(oldConsoleId.ToString(), out InputConsoles inputConsole) == true) { //Find a console with this name string consoleName = inputConsole.ToString().ToLowerInvariant(); using (BotDBContext context = DatabaseManager.OpenContext()) { GameConsole console = context.Consoles.FirstOrDefault(c => c.Name == consoleName); //Couldn't find the console if (console == null) { continue; } List <InvalidCombo> newInvalidCombo = new List <InvalidCombo>(); for (int i = 0; i < invalidCombos.Count; i++) { string inputName = invalidCombos[i]; //Try to find a valid input containing this name InputData inpData = console.InputList.FirstOrDefault(inp => inp.Name == inputName); if (inpData == null) { continue; } //Check if this button is already in an invalid combo and ignore if so InvalidCombo existing = console.InvalidCombos.FirstOrDefault(ivc => ivc.InputID == inpData.ID); if (existing != null) { continue; } //Add the invalid combo console.InvalidCombos.Add(new InvalidCombo(inpData)); context.SaveChanges(); invalidButtonCombos++; } } } } Console.WriteLine($"Completed importing {invalidButtonCombos} invalid button combos!"); /* Input Synonyms */ Console.WriteLine("Begin importing input synonyms..."); int importedSynonyms = 0; foreach (KeyValuePair <InputConsoles, Dictionary <string, string> > kvPair in oldBotData.InputSynonyms.SynonymDict) { //Skip if there are none for this console if (kvPair.Value.Count == 0) { continue; } string consoleName = kvPair.Key.ToString(); Dictionary <string, string> synonyms = kvPair.Value; using (BotDBContext context = DatabaseManager.OpenContext()) { GameConsole console = context.Consoles.FirstOrDefault(c => c.Name == consoleName); //Couldn't find the console if (console == null) { continue; } //Add all synonyms if they don't exist foreach (KeyValuePair <string, string> synonymKV in synonyms) { string synonymName = synonymKV.Key; InputSynonym synonym = context.InputSynonyms.FirstOrDefault(s => s.SynonymName == synonymName); if (synonym != null) { continue; } InputSynonym newSyn = new InputSynonym(console.ID, synonymName, synonymKV.Value); context.InputSynonyms.Add(newSyn); context.SaveChanges(); } } importedSynonyms++; } Console.WriteLine($"Completed importing {importedSynonyms} input synonyms!"); /* Other changes */ Console.WriteLine("Now importing remaining bot data..."); AddSettingStrHelper(SettingsConstants.GAME_MESSAGE, oldBotData.GameMessage); AddSettingStrHelper(SettingsConstants.INFO_MESSAGE, oldBotData.InfoMessage); AddSettingIntHelper(SettingsConstants.LAST_CONSOLE, oldBotData.LastConsole); AddSettingIntHelper(SettingsConstants.DEFAULT_INPUT_DURATION, oldBotData.DefaultInputDuration); AddSettingIntHelper(SettingsConstants.MAX_INPUT_DURATION, oldBotData.MaxInputDuration); AddSettingIntHelper(SettingsConstants.JOYSTICK_COUNT, oldBotData.JoystickCount); Console.WriteLine($"Skipping importing the last virtual controller type, as the values don't line up with 2.0+."); AccessLevels.Levels inputPermLvl = (AccessLevels.Levels)oldBotData.InputPermissions; long finalPermVal = oldBotData.InputPermissions; if (AccessLvlMap.TryGetValue(inputPermLvl, out PermissionLevels permLvl) == true) { finalPermVal = (long)permLvl; } AddSettingIntHelper(SettingsConstants.GLOBAL_INPUT_LEVEL, finalPermVal); Console.WriteLine("Finished importing all bot data!"); }
public override void ExecuteCommand(EvtChatCommandArgs args) { List <string> arguments = args.Command.ArgumentsAsList; if (arguments.Count < 2) { QueueMessage(UsageMessage); return; } string macroName = arguments[0].ToLowerInvariant(); //Make sure the first argument has at least a minimum number of characters if (macroName.Length < MIN_MACRO_NAME_LENGTH) { QueueMessage($"Input macros need to be at least {MIN_MACRO_NAME_LENGTH} characters long."); return; } if (macroName.StartsWith(Parser.DEFAULT_PARSER_REGEX_MACRO_INPUT) == false) { QueueMessage($"Input macros must start with \"{Parser.DEFAULT_PARSER_REGEX_MACRO_INPUT}\"."); return; } //For simplicity with wait inputs, force the first character in the macro name to be alphanumeric if (char.IsLetterOrDigit(arguments[0][1]) == false) { QueueMessage("The first character in input macro names must be alphanumeric."); return; } //Check for max macro name if (macroName.Length > MAX_MACRO_NAME_LENGTH) { QueueMessage($"Input macros may have up to a max of {MAX_MACRO_NAME_LENGTH} characters in their name."); return; } int curConsoleID = (int)DataHelper.GetSettingInt(SettingsConstants.LAST_CONSOLE, 1L); GameConsole consoleInstance = null; using (BotDBContext context = DatabaseManager.OpenContext()) { GameConsole curConsole = context.Consoles.FirstOrDefault(c => c.ID == curConsoleID); if (curConsole == null) { QueueMessage("Cannot validate input macro, as the current console is invalid. Fix this by setting another console."); return; } consoleInstance = new GameConsole(curConsole.Name, curConsole.InputList); } Parser parser = new Parser(); //Trim the macro name from the input sequence string macroVal = args.Command.ArgumentsAsString.Remove(0, macroName.Length + 1).ToLowerInvariant(); //Console.WriteLine(macroVal); bool isDynamic = false; //Check for a dynamic macro int openParenIndex = macroName.IndexOf('(', 0); if (openParenIndex >= 0) { //If we found the open parenthesis, check for the asterisk //This is not comprehensive, but it should smooth out a few issues if (openParenIndex == (macroName.Length - 1) || macroName[openParenIndex + 1] != '*') { QueueMessage("Invalid input macro. Dynamic macro arguments must be specified with \"*\"."); return; } if (macroName[macroName.Length - 1] != ')') { QueueMessage("Invalid input macro. Dynamic macros must end with \")\"."); return; } isDynamic = true; } //Validate input if not dynamic if (isDynamic == false) { ParsedInputSequence inputSequence = default; try { string userName = args.Command.ChatMessage.Username; //Get default and max input durations //Use user overrides if they exist, otherwise use the global values int defaultDur = (int)DataHelper.GetUserOrGlobalDefaultInputDur(userName); int maxDur = (int)DataHelper.GetUserOrGlobalMaxInputDur(userName); string regexStr = consoleInstance.InputRegex; string readyMessage = string.Empty; using (BotDBContext context = DatabaseManager.OpenContext()) { IQueryable <InputSynonym> synonyms = context.InputSynonyms.Where(syn => syn.ConsoleID == curConsoleID); readyMessage = parser.PrepParse(macroVal, context.Macros, synonyms); } inputSequence = parser.ParseInputs(readyMessage, regexStr, new ParserOptions(0, defaultDur, true, maxDur)); //Console.WriteLine(inputSequence.ToString()); if (inputSequence.ParsedInputResult != ParsedInputResults.Valid) { if (string.IsNullOrEmpty(inputSequence.Error) == true) { QueueMessage("Invalid input macro."); } else { QueueMessage($"Invalid input macro: {inputSequence.Error}"); } return; } } catch (Exception e) { QueueMessage($"Invalid input macro: {e.Message}"); return; } } string message = string.Empty; using (BotDBContext context = DatabaseManager.OpenContext()) { InputMacro inputMacro = context.Macros.FirstOrDefault(m => m.MacroName == macroName); //Not an existing macro, so add it if (inputMacro == null) { InputMacro newMacro = new InputMacro(macroName, macroVal); context.Macros.Add(newMacro); if (isDynamic == false) { message = $"Added input macro \"{macroName}\"!"; } else { message = $"Added dynamic input macro \"{macroName}\"! Dynamic input macros can't be validated beforehand, so verify it works manually."; } } //Update the macro value else { inputMacro.MacroValue = macroVal; if (isDynamic == false) { message = $"Updated input macro \"{macroName}\"!"; } else { message = $"Updated dynamic input macro \"{macroName}\"! Dynamic input macros can't be validated beforehand, so verify it works manually."; } } context.SaveChanges(); } QueueMessage(message); }