public HelpCommand() : base("help", "show this screen") { _default = Help; init = () => { foreach (CommandIdentity c in Karuta.commandIDs) { //Karuta.Write(c.name); RegisterKeyword(c.name, () => { Karuta.Write("\t" + c.name + "\t" + c.helpMessage); Karuta.Write("\tOptions:"); foreach (Option o in c.options) { Karuta.Write("\t\t -" + o.key + "\t" + o.usage); } Karuta.Write("\tKeywords:"); foreach (Keyword k in c.keywords) { Karuta.Write("\t\t " + k.keyword + "\t" + k.usage); } }); } }; //RegisterOption('c', c => this.c = c); }
public void ImgurSetup() { string imgID = Karuta.REGISTY.GetString("imgur_id"); string imgSec = Karuta.REGISTY.GetString("imgur_secret"); if (string.IsNullOrWhiteSpace(imgID) || string.IsNullOrWhiteSpace(imgSec)) { Karuta.Write("Please enter Imgur API information:"); imgID = Karuta.GetInput("Imgur API ID"); imgSec = Karuta.GetInput("Imgur API Sec"); } Karuta.LOGGER.Log("Connecting to imgur...", _appName); try { _imgurClient = new ImgurClient(imgID, imgSec); albumEndpoint = new AlbumEndpoint(_imgurClient); } catch (Exception e) { Karuta.Write("Failed to connect"); Karuta.Write(e.Message); _imgurClient = null; } Karuta.REGISTY.SetValue("imgur_id", imgID); Karuta.REGISTY.SetValue("imgur_secret", imgSec); }
async void Init() { Karuta.LOGGER.Log("Starting Discord Bot..", _appName); try { ImgurSetup(); } catch (Exception e) { Karuta.LOGGER.LogError($"Unable to initiate Imgur Connection: {e.Message}", _appName); } client = new DiscordClient(); if (string.IsNullOrWhiteSpace(_token)) { _token = Karuta.GetInput("Enter discord token"); Karuta.REGISTY.SetValue("discordToken", _token); } client.MessageReceived += MessageRecieved; client.UserJoined += UserJoined; try { await client.Connect(_token, TokenType.Bot); client.SetGame("World Domination"); //SendToAllConsoles("Bot Online"); }catch (Exception e) { Karuta.LOGGER.LogWarning($"Unable to initiate connection to discord: {e.Message}", _appName); Karuta.LOGGER.LogError(e.StackTrace, _appName, true); Karuta.Write("Unable to connect to discord..."); } }
public LightingCommand() : base("lights", "Controls lighting via phillips Lighting") { _default = Setup; _user = Karuta.REGISTY.GetString("lightUser"); bool?auto = Karuta.REGISTY.GetBool("lightAutostart"); _autoStart = (auto == null) ? false : (auto == true) ? true : false; LoadLightColors(); RegisterKeyword("on", On); RegisterKeyword("off", Off); RegisterKeyword("getColors", Color); RegisterKeyword("keepColors", KeepColor); RegisterKeyword("stop", StopColorKeeper); RegisterKeyword("saveColors", SaveColor); RegisterKeyword("autostart", () => { _autoStart = !_autoStart; Karuta.REGISTY.SetValue("lightAutostart", _autoStart); Karuta.Write("Autostart " + ((_autoStart) ? "enabled" : "disabled")); }, "enable/disable autostart"); RegisterOption('h', Hue); RegisterOption('s', Saturation); RegisterOption('b', Brightness); init = () => { // if (_autoStart) // KeepColor(); }; }
public override void Run(string[] args) { if (args.Length == 1) { Karuta.Write("The available commands are:"); /*foreach(Command c in Karuta.commands.Values) * { * Karuta.Write("\t" + c.name + "\t" + c.helpMessage); * if (c.usageMessage != null) * Karuta.Write("\t\tUsage: " + c.usageMessage); * }*/ } else { for (int i = 1; i < args.Length; i++) { if (Karuta.commands.ContainsKey(args[i])) { /*Command c = Karuta.commands[args[i]]; * Karuta.Write("\t" + c.name + "\t" + c.helpMessage); * if (c.usageMessage != null) * Karuta.Write("\t\tUsage: " + c.usageMessage);*/ } else { Karuta.Write("No such command '" + args[i] + "'"); } } } }
//Color async void Color() { if (_client == null) { Setup(); } if (!_client.IsInitialized) { Karuta.Write("Not connected to lights."); return; } LightCommand cmd = new LightCommand(); List <Light> lights = new List <Light>(); lights.AddRange(await _client.GetLightsAsync()); foreach (Light l in lights) { State state = l.State; if (state.IsReachable == false || state.IsReachable == null) { continue; } Karuta.Write("\nLight: " + l.Name + " H:" + state.Hue + " S:" + state.Saturation + " B:" + state.Brightness); } }
//private StreamReader responseReader; public override void Run(string[] args) { WebRequest request; if (args.Length == 3) { string req = GetValueOfOption(args, 'r'); if (req == null) { Karuta.Write("A request parameter must be provided"); return; } try { request = WebRequest.Create(serverURL + req); Stream response = request.GetResponse().GetResponseStream(); using (StreamReader responseReader = new StreamReader(response)) Karuta.Write(responseReader.ReadToEnd()); } catch (Exception e) { Karuta.Write(e.Message); } return; } try { request = WebRequest.Create(serverURL + "/status/sessions"); WebHeaderCollection header = new WebHeaderCollection(); if (_authToken == null) { _authToken = GetAuthToken(); } Karuta.Write("Auth: " + _authToken); header.Add("X-Plex-Token", _authToken); request.Headers = header; using (Stream response = request.GetResponse().GetResponseStream()) { using (StreamReader responseReader = new StreamReader(response)) { Karuta.Write(responseReader.ReadToEnd()); using (XmlReader reader = XmlReader.Create(new StringReader(responseReader.ReadToEnd()))) { reader.ReadToFollowing("Track"); reader.MoveToAttribute("title"); string title = reader.Value; reader.MoveToAttribute("originalTitle"); string artist = reader.Value; Karuta.Write("Now Playing:"); Karuta.Write("\t" + artist + " - " + title); } } } } catch (Exception e) { Karuta.Write(e.Message); } Close(); }
public UserCommand() : base("user", "Allows you to change the username.") { RegisterOption('s', s => { Karuta.Say("Setting username to:" + s); Karuta.USER = s; }); }
async void Save() { await _channel.SendMessage("Saving Data..."); Karuta.InvokeCommand("save", new List <string>()); Karuta.Write("Data is saved:"); _bot.SaveData(); await _channel.SendMessage("Saved!"); }
void Purge() { Karuta.REGISTY.SetValue("discordImageCommands", ""); foreach (DiscordImageCommand c in from c in _bot.interpreter.GetCommands() where c.GetType() == typeof(DiscordImageCommand) select c as DiscordImageCommand) { _bot.interpreter.RemoveCommand(c.name); } Karuta.InvokeCommand("save", new List <string>()); _channel.SendMessage("All image command data has been purged"); }
//Brightness #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously async void Brightness(string b) #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously { if (_client == null) { Setup(); } if (!_client.IsInitialized) { Karuta.Write("Not connected to lights."); return; } }
private void Start() { var karutaCSV = Resources.Load("CSV/KarutaSample") as TextAsset; var csv = CSVReader.SplitCsvGrid(karutaCSV.text); for (int i = 1; i < csv.GetLength(1) - 1; i++) { Karuta karuta = new Karuta(); karuta.SetFromCSV(GetRaw(csv, i)); karutas.Add(karuta); } setKaruta(); }
//Keep Colors private void KeepColor() { if (string.IsNullOrWhiteSpace(_user)) { _client = new LocalHueClient(_url); _client.Initialize(_user); } if (_client == null) { Setup(); } if (!_client.IsInitialized) { Karuta.Write("Not connected to lights."); return; } if (_colorKeeper != null) { Karuta.Write("Color Keeper is already running!"); return; } if (_lightColors?.Count == 0) { Karuta.Write("No colors saved."); return; } _colorKeeper = Karuta.StartTimer("Lights Color Keeper", async info => { foreach (Light l in await _client.GetLightsAsync()) { State state = l.State; if (state.Saturation == _defaultColor.s && state.Hue == _defaultColor.h && state.Brightness == (byte)_defaultColor.b) { try { Color curColor = _lightColors[l.Id]; LightCommand cmd = new LightCommand(); cmd.Hue = curColor.h; cmd.Saturation = curColor.s; await _client.SendCommandAsync(cmd, new string[] { l.Id }); }catch (Exception e) { Karuta.LOGGER.LogWarning(e.Message, nameof(LightCommand)); } } } }, 0, 1000); }
public DiscordEventCommand(DiscordBot bot) : base("events", "Add/Remove/View upcoming events") { _bot = bot; init = () => Karuta.StartTimer("DiscordEventKeeper", CheckEvents, 0, 60 * 1000); _events = new List <DiscordEvent>(); RegisterKeyword("all", ListEvents, "lists all events"); RegisterKeyword("add", AddEvent, "adds a new event, options [n]ame, [t]ime, and either [e]vent message or [c]ommand are required. Optional: [r]epeat rate, repeat [m]ode, [s]ervers"); RegisterKeyword("register", null, "register an exsisting event to be triggered on this channel on this server"); RegisterOption('n', n => eName = n, "Specify the name of an event"); RegisterOption('t', t => eTime = t, "Specify the time of an event, format: MM/DD/YYYY HH:MM"); RegisterOption('m', m => eMode = m, "Specify the mode of an event, Valid modes are: none, daily, weekly, monthly, and anually"); RegisterOption('e', e => eMessage = e, "Specify the message to be displayed when the even occurs, supports markdown formatting. Must be enclosed with quotes, can be used allongside the [c]ommand option"); RegisterOption('c', c => eCommand = c, "Specify the name of an iamge command that will be executed when the event occurs, can be used allongside the [e]vent message option"); RegisterOption('r', r => eRate = r, "Specify the rate multipler at which events will repeat, for example a value of 2 on an event of mode daily will repeat once every 2 days"); }
//Turns Lights off async void Off() { if (_client == null) { Setup(); } if (!_client.IsInitialized) { Karuta.Write("Not connected to lights."); return; } LightCommand cmd = new LightCommand(); cmd.On = false; await _client.SendCommandAsync(cmd); }
public DiscordBot() : base("discord", "a discord bot") { //Thread.CurrentThread.Name = "DiscordBot"; _default = Init; _token = Karuta.REGISTY.GetString("discordToken"); bool?auto = Karuta.REGISTY.GetBool("discordAutostart"); _autoStart = (auto == null) ? false : (auto == true) ? true : false; RegisterKeyword("stop", Stop, "stops the bot"); RegisterKeyword("autostart", () => { _autoStart = !_autoStart; Karuta.REGISTY.SetValue("discordAutostart", _autoStart); Karuta.Write($"Autostart {((_autoStart) ? "enabled" : "disabled")}"); }, "enable/disable autostart"); RegisterOption('t', s => { _token = s; Karuta.REGISTY.SetValue("discordToken", _token); Karuta.Write("Token Saved"); }, "set the token"); interpreter = new DiscordCommandInterpreter <DiscordCommand>() { adminUserID = _adminUserID, rateLimit = 5 }; RegisterSystemCommands(); LoadData(); interpreter.Init(); init = () => { if (_autoStart) { _default(); } }; }
//Save current Colors private async void SaveColor() { if (_client == null) { Setup(); } if (!_client.IsInitialized) { Karuta.Write("Not connected to lights."); return; } List <Light> lights = new List <Light>(); lights.AddRange(await _client.GetLightsAsync()); foreach (Light l in lights) { State state = l.State; if (state.IsReachable == true) { if (_lightColors.ContainsKey(l.Id)) { _lightColors[l.Id] = new Color((int)state.Hue, (int)state.Saturation, state.Brightness); } else { _lightColors.Add(l.Id, new Color((int)state.Hue, (int)state.Saturation, state.Brightness)); } } } string data = ""; foreach (string s in _lightColors.Keys) { if (data != "") { data += "|"; } data += s + "`" + _lightColors[s].ToString(); } Karuta.REGISTY.SetValue("lightColors", data); Karuta.Write("Colors Saved!"); }
public override void Stop() { /*if(client != null) * { * foreach(Server s in client.Servers) * { * Karuta.Write(s.Name); * foreach(Channel c in s.FindChannels("console", null, true)) * { * await c.SendMessage("Bot shutting down..."); * } * } * } * Thread.Sleep(2 * 1000);*/ Karuta.Write("Shutting down..."); Karuta.LOGGER.Log("Shutting down bot...", _appName); client?.Disconnect(); client = null; SaveData(); }
public TestCommand() : base("test", "test") { _default = () => { Karuta.Write((DateTime.Now - DateTime.Now.AddSeconds(25)).TotalSeconds); Karuta.CreateThread("testThread", () => Karuta.Write("Test")).Abort(); }; RegisterOption('t', t => { int time; if (int.TryParse(t, out time)) { Timer timer = new Timer(info => { Karuta.Write(DateTime.Now.Second); }, null, 0, time); } }); }
public override void Run(string[] args) { if (args.Length < 4) { Karuta.Write("too few arguments"); return; } string size = GetValueOfOption(args, 's'); if (size == null) { Karuta.Write("no size provided"); return; } int optionPos = GetIndexOfOption(args, 's'); int valueStackSize = GetValueStackSize(args, optionPos); string shape; if (optionPos + valueStackSize > args.Length) { shape = args[optionPos + valueStackSize + 1]; } else { shape = args[optionPos - 2]; } if (shape == null) { Karuta.Write("Error"); return; } if (validShapes.Contains(shape)) { DrawShape(shape); } else { Karuta.Write("Invalid Shape"); Karuta.Write(usageMessage); } }
void ListAll() { if (_threads.Count != 0) { Karuta.Write("\tThreads:"); Karuta.Write("\t\tName \t\t Thread State"); foreach (Thread t in _threads.Values) { Karuta.Write($"\t\t{t.Name}\t\t{t.ThreadState}"); } } if (_timers.Count != 0) { Karuta.Write("\tTimers:"); foreach (string t in _timers.Keys) { Karuta.Write($"\t\t{t}"); } } }
//Setup async void Setup() { _client = new LocalHueClient(_url); try { if (_user == "" || _user == null) { _user = await _client.RegisterAsync("Karuta.lighting", "Karuta"); } else { _client.Initialize(_user); } }catch (Exception e) { Karuta.Write(e.Message); Karuta.Write(e.StackTrace); } Karuta.REGISTY.SetValue("lightuser", _user); List <Light> light = new List <Light>(); }
public ProcessMonitor(Dictionary <string, Thread> threadList, Dictionary <string, Timer> timers) : base("processes", "lists and manages threads and timers") { _threads = threadList; _timers = timers; _default = ListAll; List <Thread> removalQ = new List <Thread>(); init = () => { //Start Thread Monitor Karuta.StartTimer("ThreadMonitor", e => { removalQ.Clear(); removalQ.AddRange(from thread in _threads.Values where thread.ThreadState == ThreadState.Aborted || thread.ThreadState == ThreadState.Stopped select thread); foreach (Thread thread in removalQ) { Karuta.LOGGER.Log($"Thread \"{thread.Name}\" has been {thread.ThreadState} and will be removed", appName); Karuta.CloseThread(thread); } }, 5 * 1000, 5 * 1000); }; }
void Help() { if (c != null) { CommandIdentity cmd = (from CommandIdentity cID in Karuta.commandIDs where cID.name == c select cID).First(); if (cmd != null) { Karuta.Write("\t" + cmd.name + "\t" + cmd.helpMessage); Karuta.Write("\tOptions:"); foreach (Option o in cmd.options) { Karuta.Write("\t\t -" + o.key + "\t" + o.usage); } Karuta.Write("\tKeywords:"); foreach (Keyword k in cmd.keywords) { Karuta.Write("\t\t " + k.keyword + "\t" + k.usage); } } else { Karuta.Write("No such command '" + c + "'"); } c = null; } else { Karuta.Write("The available commands are:"); foreach (CommandIdentity c in Karuta.commandIDs) { Karuta.Write("\t" + c.name + "\t" + c.helpMessage); //if (c.usageMessage != null) // Karuta.Write("\t\tUsage: " + c.usageMessage); } } }
public override void Run(string[] args) { if (args.Length == 1) { Karuta.Say("The current username is: " + Karuta.user); return; } if (args.Length < 3) { Karuta.Write("Not enough parameters"); Karuta.Write(usageMessage); return; } string user = GetValueOfOption(args, 's'); if (user == null) { Karuta.Write("Username must be specified"); Karuta.Write(usageMessage); return; } Karuta.Say("Setting username to: " + user); Karuta.user = user; }
private string GetAuthToken() { if (_cookies == null) { GetCookies(); } string pass = Karuta.GetInput("Please enter your Plex password", true); string postData = String.Format("user[login]={0}&user[password]={1}", Karuta.user, pass); HttpWebRequest getRequest = (HttpWebRequest)WebRequest.Create("https://my.plexapp.com/users/sign_in.xml"); getRequest.CookieContainer = new CookieContainer(); getRequest.CookieContainer.Add(_cookies); //recover cookies First request getRequest.Method = WebRequestMethods.Http.Post; getRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2"; getRequest.AllowWriteStreamBuffering = true; getRequest.ProtocolVersion = HttpVersion.Version11; getRequest.AllowAutoRedirect = true; getRequest.ContentType = "application/x-www-form-urlencoded"; byte[] byteArray = Encoding.ASCII.GetBytes(postData); getRequest.ContentLength = byteArray.Length; Stream newStream = getRequest.GetRequestStream(); //open connection newStream.Write(byteArray, 0, byteArray.Length); // Send the data. newStream.Close(); HttpWebResponse response = (HttpWebResponse)getRequest.GetResponse(); //Retrieve your cookie that id's your session //response.Cookies StreamReader reader = new StreamReader(response.GetResponseStream()); string output = reader.ReadToEnd(); reader.Close(); reader.Dispose(); response.Close(); return(output); }
public virtual ICommand Parse(List <string> args) { //Find keyword to execute Keyword selectedKeyword = null; if ((_keywords.Count == 0 && _options.Count == 0) || args.Count == 0) { return(Execute()); } Debug.Print("Raw Args"); Debug.Print(string.Join(" ", from s in args select s)); Debug.Print("Keyword parse START"); if (_keywords.Count != 0) { //Select and assign the keyword if it exists //IList<Keyword> kl = (from arg in args where _keywords.ContainsKey(arg) select _keywords[arg]).ToList(); //selectedKeyword = (kl.Count == 0) ? null : kl.First(); if (_keywords.TryGetValue(args[0], out selectedKeyword)) { args.Remove(selectedKeyword.keyword); } } Debug.Print("Keyword parse END"); Debug.Print($">{string.Join(", ", from s in args select s)}"); //Find options to set if (args.Count != 0) { IList <string> emptyArgs = (from empty in args where string.IsNullOrWhiteSpace(empty) select empty).ToList(); foreach (string arg in emptyArgs) { args.Remove(arg); } Debug.Print($">{string.Join(", ", from s in args select s)}"); string optKeys = ""; Debug.Print("Option flags parse START"); //Find options flags optKeys = string.Join("", from o in args where o.Contains("-") select o.Remove(0, 1)); List <string> removalQ = new List <string>(); removalQ.AddRange(from a in args where a.Contains("-") select a); foreach (string a in removalQ) { args.Remove(a); } Debug.Print("Option flags parse END"); Debug.Print($">{string.Join(", ", from s in args select s)}"); Debug.Print($">{string.Join(", ", from s in args select s)}"); int index = 0; Debug.Print("Option parse START"); //Execute each option and pass pararemter if needed foreach (char key in optKeys) { Option opt; if (!_options.TryGetValue(key, out opt)) { throw new CommandParsingExeception($"No such option -{key.ToString()} {optKeys}"); } if (opt.isParamLess) { opt.Execute(); } else { if (args.Count <= index) { Karuta.Write("No value provided for option: " + opt.key); } else { opt.Execute(args[index++]); } } } Debug.Print("Option parse END"); Debug.Print($">{string.Join(", ", from s in args select s)}"); } Debug.Print("EXECUTE"); //Execute keyword if found if (selectedKeyword != null) { selectedKeyword.Execute(); return(this); } //Execute default return(Execute()); }
async void Remove() { //Validate List <string> imageLinks = new List <string>(); Uri url = new Uri(_url); if (!_removeEntirely) { if (_name == null || _url == null || _url == "" || _name == "") { await _channel.SendMessage("An image name and url must be specified"); return; } if (_url.Contains('`') || _url.Contains('{')) { await _channel.SendMessage("Invalid URL"); return; } if (url.Host == "i.imgur.com") { if (_bot.validExtensions.Contains(Path.GetExtension(url.AbsolutePath))) { imageLinks.Add(_url); } } else if (url.Host != "imgur.com") { await _channel.SendMessage("Only imgur images are allowed"); return; } } else if (_name == null || _name == "") { await _channel.SendMessage("An image name must be specified"); return; } //Resolve Link if (imageLinks.Count == 0 && !_removeEntirely) { imageLinks = await _bot.ResolveImgurUrl(url); } if (_bot.interpreter.CommandExists(_name)) { int removed = 0, skipped = 0; if (_removeEntirely) { _bot.interpreter.RemoveCommand(_name); } else { if (_bot.interpreter.GetCommand(_name).GetType() != typeof(DiscordImageCommand)) { await _channel.SendMessage("This is not an image command"); } DiscordImageCommand cmd = ((DiscordImageCommand)_bot.interpreter.GetCommand(_name)); foreach (string i in cmd.images) { Karuta.Write(i); } foreach (string u in imageLinks) { if (cmd.RemoveImage(u)) { removed++; } else { skipped++; } } foreach (string i in cmd.images) { Karuta.Write(i); } if (cmd.images.Count == 0) { _bot.interpreter.RemoveCommand(_name); } } await _channel.SendMessage($"{removed} Image{((removed > 1) ? "s" : "")} removed"); if (skipped != 0) { await _channel.SendMessage($"{skipped} Image{((skipped > 1) ? "s" : "")} were not found, and skipped"); } } else { await _channel.SendMessage("that image command does not exsist"); } _bot.interpreter.GetCommandOfType <HelpCommand>()?.init(); _bot.SaveData(); Karuta.InvokeCommand("save", new List <string>()); _removeEntirely = false; _url = _name = null; }
async void Add() { //Validate if (string.IsNullOrWhiteSpace(_name) && string.IsNullOrWhiteSpace(_url)) { await _channel.SendMessage($"An image name and url must be specified, use !help {name} for more info"); return; } if ((_url.Contains('`') || _url.Contains('{'))) { await _channel.SendMessage("Invalid URL"); return; } List <string> imageLinks = new List <string>(); Uri url = new Uri(_url); if (url.Host == "i.imgur.com") { if (_bot.validExtensions.Contains(Path.GetExtension(url.AbsolutePath))) { imageLinks.Add(_url); } } else if (url.Host != "imgur.com") { await _channel.SendMessage("Only imgur images are allowed"); return; } //Resolve Link if (imageLinks.Count == 0) { imageLinks = await _bot.ResolveImgurUrl(url); } //Add Command if (_bot.interpreter.CommandExists(_name)) { DiscordCommand c = _bot.interpreter.GetCommand(_name); if (c?.GetType() == typeof(DiscordImageCommand)) { DiscordImageCommand cmd = (DiscordImageCommand)c; int dupeCount = 0; int addCount = 0; if (!string.IsNullOrWhiteSpace(_help)) { cmd.SetHelpMessage(_help); } foreach (string link in imageLinks) { if (cmd.images.Contains(link)) { dupeCount++; continue; } cmd.AddImage(link); addCount++; } if (dupeCount > 0) { await _channel.SendMessage($"{dupeCount} Image{((dupeCount > 1) ? "s" : "")} already existed and were not added"); } await _channel.SendMessage($"{addCount} Image{((addCount > 1) ? "s" : "")} Added"); //await _channel.SendMessage(cmd.ToString()); } else { await _channel.SendMessage("This name cannot be used"); } } else { //Karuta.Write(count); DiscordImageCommand img = (_help != default(string)) ? new DiscordImageCommand(_name, _help) { images = imageLinks } :new DiscordImageCommand(_name) { images = imageLinks }; _bot.interpreter.RegisterCommand(img); img.init?.Invoke(); _bot.interpreter.GetCommandOfType <DiscordHelpCommand>()?.init(); await _channel.SendMessage($"{imageLinks.Count} Image{((imageLinks.Count > 1) ? "s" : "")} Command Added"); Karuta.Write(img.ToString()); } //foreach (string c in bot.commands.Keys) // _channel.SendMessage(c); _bot.SaveData(); Karuta.InvokeCommand("save", new List <string>()); _url = _name = null; }