sylae / ligrev

XMPP MUC Utility bot
GNU General Public License v3.0
2 stars 1 forks source link

Use QueryPath to assemble stanzas where possible. #17

Closed sylae closed 7 years ago

sylae commented 8 years ago

JAXL is an ass about sending text-only messages. I cannot seem to locate a method to send HTML messages using it. However, we can make like ligrevCommand::kickOccupant() and send a raw payload to go over JAXL's helmet.

cburschka commented 8 years ago

There's a particular format for adding a XHTML component to a stanza, IIRC... maybe JAXL has a special method for it?

cburschka commented 8 years ago
    public function __construct($attrs, $body=null, $thread=null, $subject=null) {
        parent::__construct('message', $attrs);

        if($body) $this->c('body')->t($body)->up();
        if($thread) $this->c('thread')->t($thread)->up();
        if($subject) $this->c('subject')->t($subject)->up();
    }

Yeah, you can't pass HTML into that.

You need to attach the XHTML node to the object that method returns somehow.

cburschka commented 8 years ago

FFS, why doesn't JAXL have something that can parse HTML to its XML object structure? :|

The only obvious way to add markup it is something like this:

$msg = new XMPPMsg($attrs, $text)
  ->c('html', 'http://jabber.org/protocol/xhtml-im')
  ->c('body', 'http://www.w3.org/1999/xhtml')
  ->c('p', NULL, ['style' => 'color:red'], 'Hello World');
sylae commented 8 years ago

If we're doing HTML we'll also need to send a plaintext option. As with cadence, probably sending Markdown is preferable. You just used xbbcode-js with custom tags for that, yeah?

I guess a solution is just to write the code using markdown, and then convert it to xhtml and send it like that, using whatever people render markdown with

cburschka commented 8 years ago

Come to think of it, I don't think JAXL does any typechecking on the actual nodes you attach. You can probably use any XML library you want, or for that matter inject arbitrary raw XML by creating your own object-wrapper that implements "to_string()".

class RawXML {
  private $string;
  public function __construct($string) {
    $this->string = $string;
  }
  public function to_string() {
    return $this->string;
  }
}

$msg = new XMPPMsg($attrs, $text)
  ->c('html', 'http://jabber.org/protocol/xhtml-im')
  ->c('body', 'http://www.w3.org/1999/xhtml')
  ->cnode(new RawXML('<p style="color:red">Hello World</p>'));
sylae commented 8 years ago

Yeah, I'm basically doing that to kick people. See the code here: https://github.com/sylae/ligrev/blob/master/classes/ligrevCommand.php#L48

(dunno how to do fancy github syntax to link to that). Ideally, we can use something like querypath to render the xml string "properly" instead of just throwing a string at JAXL

cburschka commented 8 years ago

Oh right, QP can totally do that. You'd just need to wrap it a bit so it can automatically use the right XML namespace, and also alias to_string() to QP's html()...

class JAXL_QP_Bridge_Thingy {
   const DOCUMENT = '<html xmlns="http://jabber.org/protocol/xhtml-im"><body xmlns="http://www.w3.org/1999/xhtml"></body></html>';
   protected $qp;
   public function __construct($html = NULL) {
     $this->qp = \qp(self::DOCUMENT);
     if ($html) $this->append($html);
   }
   public function append($html) {
     $this->qp->find('body')->append($html);
     return $this;
   }
   public function to_string() {
     return $this->qp->html();
   }
}

$msg = new XMPPMsg($attrs, $text)
  ->cnode(new JAXL_QP_Bridge_Thingy('<p style="color:red">Hello World</p>'));
sylae commented 8 years ago

it turns out qp reeeeaaaallly likes adding and <!DOCTYPE> to everything. Like, it's kinda weird.

Also, refuses to take any html I give it, which is kind of a pain. Whatevs.

cburschka commented 8 years ago

That sounds odd; it didn't add a doctype when I used the thing above...

Edit: Dammit, now it does. :|

Edit: Looks like it adds it whenever an <html> is the top node. Maybe...

sylae commented 8 years ago

Well, that's when I get it to get that far. Most of my attempts to pass a raw html string to qp result in it exiting with no message whatsoever when calling append() (I suspect I'm fucking something up somewhere, but eh).

In any case, I have it working using your rawXML class. I'm gonna revisit this and try to figure out why I'm having trouble getting querypath to play nice, as I'd prefer to do all my work in there where possible.

cburschka commented 8 years ago

This wrapper just gets more and more complex :p

https://gist.github.com/cburschka/1347154a744b61b93a97

(Basically, instead of outputting the whole thing, this should just find the <body> and wrap it in <html></html> directly.)

sylae commented 8 years ago

So JAXLXml, while a bit clunky, is pretty decent for writing stanzas, at least the simple ones. QP, however, is superb as far as reading them goes. So we'll probably use each tool for what it does best.

In any case, the only thing really using hard-coded XML is the kickOccupant function, handily located in the messageHandler class for some reason. Once that's fixed we should be okay.

sylae commented 7 years ago

iirc, the only thing that was using hard-coded XML still was the kick command, which was fixed awhile ago.

as far as using querypath for writes, fuck that.