git » sdk » main » tree

[main] / borogove / queries / CommandExecute.hx

package borogove.queries;

import haxe.DynamicAccess;
import haxe.Exception;

import borogove.ID;
import borogove.ResultSet;
import borogove.Stanza;
import borogove.queries.GenericQuery;
import borogove.Caps;
import borogove.Command;
import borogove.DataForm;
using borogove.Util;
using Lambda;

class CommandExecute extends GenericQuery {
	public var xmlns(default, null) = "http://jabber.org/protocol/commands";
	public var queryId:String = null;
	public var responseStanza(default, null):Stanza;
	private var result: Null<CommandSession>;
	private final node: String;

	public function new(to: String, node: String, ?action: Null<String>, ?sessionid: Null<String>, ?payload: Null<Stanza>) {
		this.node = node;
		var attr: DynamicAccess<String> = { xmlns: xmlns, node: node };
		attr["action"] = action ?? "execute";
		if (sessionid != null) attr["sessionid"] = sessionid;
		/* Build basic query */
		queryId = ID.short();
		queryStanza = new Stanza(
			"iq",
			{ to: to, type: "set", id: queryId }
		).tag("command", attr);
		if (payload != null) queryStanza.addChild(payload);
		queryStanza.up();
	}

	public function handleResponse(stanza:Stanza) {
		responseStanza = stanza;
		finish();
	}

	@:access(borogove.Form.form)
	public function getResult(command: Command) {
		if (responseStanza == null) {
			return null;
		}
		if(result == null) {
			final cmd = responseStanza.getChild("command", xmlns);
			if (responseStanza.attr.get("type") == "error" || cmd == null) {
				result = new CommandSession(
					"error",
					queryStanza.attr.get("sessionid"),
					[],
					forms([responseStanza]),
					command
				);
				return result;
			}

			if (
				queryStanza.attr.get("sessionid") != null &&
				cmd.attr.get("sessionid") != queryStanza.attr.get("sessionid")
			) {
				trace("sessionid mismatch", queryStanza, cmd);
				return null;
			}
			final forms = forms(cmd.allTags());
			final execute = cmd.getChild("actions")?.attr?.get("execute");
			final extActionsField = forms[0]?.form?.field("http://jabber.org/protocol/commands#actions");
			if (extActionsField != null) extActionsField.type = "hidden";
			final extActions: Array<FormOption> = (extActionsField?.options ?? []).map(o -> o.toFormOption());
			final actions = extActions.length > 0 ? extActions : (cmd.getChild("actions")?.allTags()?.map(s -> new FormOption(s.name.capitalize(), s.name))?.filter(o -> o.value != "execute") ?? []);
			if (cmd.attr.get("status") == "executing") {
				if (actions.length < 1) actions.push(new FormOption("Go", "execute"));
				if (actions.find(a -> a.value == "cancel") == null) actions.push(new FormOption("Cancel", "cancel"));
			}
			actions.sort((x,y) -> x.value == execute ? -1 : (y.value == execute ? 1 : 0));
			result = new CommandSession(
				cmd.attr.get("status"),
				cmd.attr.get("sessionid"),
				actions,
				forms,
				command
			);
		}
		return result;
	}

	private function forms(els: Array<Stanza>): Array<Form> {
		final fs = [];
		for (el in els) {
			if (el.name == "x" && el.attr.get("xmlns") == "jabber:x:data") {
				fs.push(new Form(el, null));
			}
			if (el.name == "x" && el.attr.get("xmlns") == "jabber:x:oob") {
				fs.push(new Form(null, el));
			}
			if (el.name == "iq" && el.attr.get("type") == "error") {
				final error = el.getError();
				final formish = new Stanza("x", { xmlns: "jabber:x:data", type: "result" }).textTag("instructions", error.text ?? error.condition, { type: "error" });
				fs.push(new Form(formish, null));
			}
			if (el.name == "note") {
				final formish = new Stanza("x", { xmlns: "jabber:x:data", type: "result" }).textTag("instructions", el.getText(), { type: el.attr.get("type") });
				fs.push(new Form(formish, null));
			}
		}
		return fs;
	}
}