using System; using System.Collections.Generic; using System.Text; using System.Linq; using OpenMetaverse; using System.Net.Http; using BSB.bottypes; using BetterSecondBotShared.API; using BetterSecondBotShared.Static; using BetterSecondBotShared.logs; namespace BSB.Commands { public class pending_avatar_lookup { public CoreCommand GetCommand { get { return Command; } } public List Getargs { get { return args; } } public pending_avatar_lookup(CoreCommandsInterface set_master,CoreCommand set_cmd,string[] set_args) { Master = set_master; Command = set_cmd; args = set_args.ToList(); } public KeyValuePair Callnow() { bool result = Command.CallFunction(args.ToArray()); return new KeyValuePair(result, Command.GetInfoBlob); } public bool needs_lookup() { List need_lookup_on_indexs = new List(); int loop = 0; foreach (string atype in Command.ArgTypes) { if (loop < args.Count) { if (atype == "Avatar") { need_lookup_on_indexs.Add(loop); } else if(atype == "Smart") { if(args[loop].StartsWith("http") == false) { // not a url request if (int.TryParse(args[loop],out _) == false) { // Not a channel need_lookup_on_indexs.Add(loop); } } } loop++; } else { break; } } bool has_required_lookups = false; foreach (int A in need_lookup_on_indexs) { if(UUID.TryParse(args[A],out _) == false) { // not a uuid string get_or_request_uuid = Master.GetBot.FindAvatarName2Key(args[A]); if(get_or_request_uuid == "lookup") { has_required_lookups = true; } else { args[A] = get_or_request_uuid; } } } return has_required_lookups; } protected CoreCommand Command; protected List args; protected CoreCommandsInterface Master; } public class CoreCommandsInterface : API_supported_interface { protected CommandsBot bot; public CommandsBot GetBot { get { return bot; } } protected long giveup_waiting_for_lookup = 240; protected int next_lookup_id; protected Dictionary commands_pending_avatar_lookups = new Dictionary(); protected Dictionary commands_pending_avatar_lookups_ages = new Dictionary(); public void StatusTick() { List purge_indexs = new List(); List call_indexs = new List(); long now = helpers.UnixTimeNow(); foreach (KeyValuePair pair in commands_pending_avatar_lookups_ages) { if (commands_pending_avatar_lookups[pair.Key].needs_lookup() == true) { long dif = now - pair.Value; if (dif > giveup_waiting_for_lookup) { purge_indexs.Add(pair.Key); } } else { call_indexs.Add(pair.Key); } } foreach(int a in purge_indexs) { commands_pending_avatar_lookups_ages.Remove(a); commands_pending_avatar_lookups.Remove(a); } foreach(int a in call_indexs) { KeyValuePair result = commands_pending_avatar_lookups[a].Callnow(); bot.CommandHistoryAdd(commands_pending_avatar_lookups[a].GetCommand.CommandName, String.Join("~#~", commands_pending_avatar_lookups[a].Getargs), result.Key, result.Value); commands_pending_avatar_lookups_ages.Remove(a); commands_pending_avatar_lookups.Remove(a); } } public CoreCommandsInterface(CommandsBot linktobot) { bot = linktobot; API_type = typeof(CoreCommand); LoadCommandsList(); } protected HttpClient HTTPclient = new HttpClient(); public bool SmartCommandReply(string target, string output) { return SmartCommandReply(target, output, ""); } public bool SmartCommandReply(string target, string output, string command) { string mode = "CHAT"; UUID target_avatar = UUID.Zero; int target_channel = 0; if (target.StartsWith("http://")) { mode = "HTTP"; } else if (UUID.TryParse(target, out target_avatar) == true) { mode = "IM"; } else { int.TryParse(target, out target_channel); } if (mode == "CHAT") { bot.GetClient.Self.Chat(output, target_channel, ChatType.Normal); } else if (mode == "IM") { bot.GetClient.Self.InstantMessage(target_avatar, output); } else if (mode == "HTTP") { Dictionary values = new Dictionary { { "reply", output }, { "unixtime", helpers.UnixTimeNow().ToString() } }; if (command != "") { values.Add("command", command); } var content = new FormUrlEncodedContent(values); try { HTTPclient.PostAsync(target, content); } catch (Exception e) { ConsoleLog.Crit("[SmartReply] HTTP failed: " + e.Message + ""); } } else { return false; } return true; } protected List suppress_warnings = new List(); public bool Call(string command) { return Call(command, ""); } public bool Call(string command, string arg) { return Call(command, arg, UUID.Zero); } public bool Call(string command, string arg, UUID caller) { return Call(command, arg, caller, "~#~"); } public bool Call(string command, string arg, UUID caller, string split_args_on) { KeyValuePair result = CallCommand(command, arg, caller, split_args_on); bot.CommandHistoryAdd(command, arg, result.Key, result.Value); return result.Key; } protected KeyValuePair CallCommand(string command, string arg, UUID caller, string split_args_on) { command = command.ToLowerInvariant(); CoreCommand cmd = (CoreCommand)GetCommand(command); if (cmd != null) { cmd.Setup(bot, caller); string[] args = new string[] { }; if (helpers.notempty(arg) == true) { args = arg.Split(new[] { split_args_on }, StringSplitOptions.RemoveEmptyEntries); } if ((cmd.ArgTypes.Contains("Avatar") == true) || (cmd.ArgTypes.Contains("Smart") == true)) { if (cmd.Min_Required_args <= args.Length) { pending_avatar_lookup pending = new pending_avatar_lookup(this, cmd, args); if (pending.needs_lookup() == true) { commands_pending_avatar_lookups.Add(next_lookup_id, pending); commands_pending_avatar_lookups_ages.Add(next_lookup_id, helpers.UnixTimeNow()); next_lookup_id++; if (next_lookup_id == 13000) { next_lookup_id = 0; } return new KeyValuePair(true,"Lookup underway"); } else { return pending.Callnow(); } } else { return new KeyValuePair(false, "Required args count not sent! expected: "+ cmd.Min_Required_args.ToString()+" but got "+ args.Length.ToString()+ ""); } } else { bool result = cmd.CallFunction(args); return new KeyValuePair(result, cmd.GetInfoBlob); } } else { if (suppress_warnings.Contains(command) == false) { suppress_warnings.Add(command); return new KeyValuePair(false, "unknown"); } } return new KeyValuePair(false, "--"); } } public abstract class CoreCommand_1arg : CoreCommand { public override int Min_Required_args { get { return 1; } } } public abstract class CoreCommand_2arg : CoreCommand { public override int Min_Required_args { get { return 2; } } } public abstract class CoreCommand_3arg : CoreCommand { public override int Min_Required_args { get { return 3; } } } public abstract class CoreCommand_4arg : CoreCommand { public override int Min_Required_args { get { return 4; } } } public abstract class CoreCommand_SmartReply_1arg : CoreCommand_1arg { public override string[] ArgTypes { get { return new[] { "Smart" }; } } public override string[] ArgHints { get { return new[] { "Mixed [Channel|Avatar uuid|Avatar name|http url]" }; } } } public abstract class CoreCommand : API_interface { protected CommandsBot bot; /// /// The UUID of the object/Avatar that called this function, you should still test if its not UUID zero and is a avatar /// protected UUID caller = UUID.Zero; public void Setup(CommandsBot setBot,UUID setCaller) { bot = setBot; caller = setCaller; } public virtual void Callback(string[] args, EventArgs e,bool status) { bot.CommandHistoryAdd("Callback finished-> " + this.GetType().Name, String.Join(",", args), status, GetInfoBlob); } public virtual void Callback(string[] args, EventArgs e) { bot.CommandHistoryAdd("Callback finished-> " + this.GetType().Name, String.Join(",", args), true, GetInfoBlob); } public virtual bool CallFunction(string[] args) { if (helpers.notempty(args) == true) { if (args.Length < Min_Required_args) { return Failed("Incorrect number of args"); } else { return true; } } else { if(Min_Required_args == 0) { return true; } else { return Failed("Incorrect number of args"); } } } public bool Failed(string why_failed) { InfoBlob = why_failed; return false; } } }