/me command

Chris D

XenForo developer
Staff member
I originally posted a request for an add on to be made for me, but since then I have decided to have a go at making it myself.

The simple premise is the good old /me command as seen in numerous chat systems including mIRC and Steam. So, if I were to type in a post: /me would like to create an add on then it would get transformed into:

* Yorick would like to create an add on

Some have questioned the need and/or feasibility of such an add on, but with it being available natively in myBB and SMF and available as a mod in vBulletin then I'm sure it's very feasible.

And actually I've made some progress:

PHP:
<?php
class Me_EventListener_TemplatePostRender
{
        static public function listen($templateName, &$output, &$containerData, XenForo_Template_Abstract $template){
                if($templateName == 'thread_view'){
                $me = {$message.username};
                $output = preg_replace('#(>|^|\r|\n)/me ([^\r\n<]*)#i', "<b>\\1 * '{$me}' \\2</b>", $output);
                }
                }
                }

So actually this code is broken. The reason it is broken is because $message.username or $message is undefined. $message.username is used in the message and post templates to call the post author's username.

If $me = 'Yorick' then actually the code works how I want - but /me will always transform into Yorick instead of the actual author's username.

So I feel like we're close.

I can get around the aforementioned error regarding the variable being undefined by changing the $templateName to 'message' or 'post' as they must be defined there. But unfortunately - and I don't know why - doing so completely ignores the /me code.

Any help gratefully received. Once we have this working we are going to release it ourselves on the Resource Manager so hopefully anyone else in the future can make use of this.


EDIT: We did start work on a slightly different variation where instead of replacing /me with the contents of a variable instead we tried to get /me to call a template which would call the variable. Is that something that might work better?
 
That code event only works for templates that are called with the template object. That means it only works with content templates (e.g. thread_view) and containers (e.g. PAGE_CONTAINER). It doesn't work with inlined templates like "message".

As for the $message.username problem... you will need to get the post records from the template params, like so:

Code:
$posts = $template->getParam('posts');

This is an array of posts. You can parse through them with a foreach. However, with the template_post_render event the template has already been rendered so modifying the post records doesn't do you much good at that point.

I recommend extending the view class instead (XenForo_ViewPublic_Thread_View). In the view you can access the posts with $this->_params['posts'] and make appropriate string replacements before the template is rendered.
 
Oh yeah I've missed this. I'm surprised no one's made this yet since there are a lot of gaming xenforo forums.
 
The8thLegion, I absolutely agree. It's also commonly featured as an add on for vBulletin and is even a core feature in myBB, SMF and some other forums. I'm not saying it'd be widely used enough to constitute a core feature but certainly a brilliant candidate for an add on and actually I think it'd be more widely used than we think.

I've PM'd you Jake. I can't thank you enough for taking the time to reply, but I might need a little more help.
 
I was going to make a skeleton for you, but it's such a simple addon I just finished it myself. It replaces /me in posts with the name of the author. You can look at the code to see how it works. However it doesn't work for post previews or for newly submitted quick reply posts (until you refresh anyways). Probably need to extend the bb code system to make it work for those other areas.
 

Attachments

I was going to make a skeleton for you, but it's such a simple addon I just finished it myself. It replaces /me in posts with the name of the author. You can look at the code to see how it works. However it doesn't work for post previews or for newly submitted quick reply posts (until you refresh anyways). Probably need to extend the bb code system to make it work for those other areas.
Jake, I cannot thank you enough. It was above and beyond what I was asking for and I am so incredibly grateful.

I have, however, found a small bug...

And it's related to quoting posts. So if I post

/me thinks you are cool.

If you were to quote that, instead of "Yorick thinks you are cool" the quote would say:

Jake Bunce thinks you are cool.

I fear there might not be an easy fix for this as I have seen similar bugs with other add ons on other forums with similar functionality. I will keep playing with the code, in the meantime, any advice?
 
In the extended view you have access to the raw HTML of the posts. I suppose you could use regex matching to identify /me inside of a quote block, but that then gets a little more complicated. It's all string manipulation inside of that foreach.
 
Jake,

I have expanded your code somewhat to include another type of command which is called /slap.

Furthermore, I have overcome the quote problem by looking for a match in the html code for data-author= and extracting the original poster's username that way:

PHP:
<?php
 
class MeSlap_ThreadView extends XFCP_MeSlap_ThreadView
{
    public function renderHtml()
    {
        parent::renderHtml();
 
        foreach ($this->_params['posts'] AS &$post)
        {
        $re = '/(?<=author=")(?:.*?)(?=")/ui';
        $txt = $post['messageHtml'];
        $nMatches = preg_match($re, $txt, $aMatches);
        if($nMatches == 1)
            {$post['messageHtml'] = preg_replace('#(>|^|\r|\n)/me ([^\r\n<]*)#i', '\\1<span class="me"> * '.$aMatches[0].' \\2 </span>', $post['messageHtml']);
            $post['messageHtml'] = preg_replace('#(>|^|\r|\n)/slap ([^\r\n<]*)#i', '\\1<span class="slap"> * '.$aMatches[0].' slaps \\2 around a bit with a large trout.</span>', $post['messageHtml']);}
        else
            $post['messageHtml'] = preg_replace('#(>|^|\r|\n)/slap ([^\r\n<]*)#i', '\\1<span class="slap"> * '.$post['username'].' slaps \\2 around a bit with a large trout.</span>', $post['messageHtml']);
            $post['messageHtml'] = preg_replace('#(>|^|\r|\n)/me ([^\r\n<]*)#i', '\\1<span class="me"> * '.$post['username'].' \\2 </span>', $post['messageHtml']);
        }
    }
}

If there are matches is uses the data-author username, if there aren't it uses the post username.

I've added some styling too.

What do you think? :D

There is one small bug. If there are two quotes in a post, it still doesn't work properly but I think that's normally quite rare :)
 
Hi Diana,

It currently only works in the thread view - I'm not familiar with Taigachat but it may not work straight away.

I am going to release this officially as an add on first, I will post the link here when I have. Maybe we'll see about getting it to work then. If you have a go in the meantime, good luck.

Jake: THANK YOU. Again. (y)
 
Top Bottom