Hubot: Class' methods are not overridden in Rocket.Chat / Meteor / JavaScript

124 Views Asked by At

Rocket.Chat has deprecated and removed Internal Hubot functionality, but in our company we have some script that can't be moved to external bot at this moment, so we wanted to maintain Internal Hubot functionality on our own (since we already have custom fork because of LDAP related changes).

I was able to make it work, almost. Internal Hubot was initialized, scripts were loaded. But calling some command returned Meteor code must always run within a Fiber (...) error.

After some debugging it seems like the core issue here is class inheritance for Hubot's robot and adapter does not work. There are custom classes that extends Hubot's package ones:

export class InternalHubotRobot extends Hubot.Robot {
    constructor(name, alias) {
        super(null, 'shell', false, name, alias);

        this.hear = bind(this.hear);
        this.respond = bind(this.respond);
        this.enter = bind(this.enter);
        this.leave = bind(this.leave);
        this.topic = bind(this.topic);
        this.error = bind(this.error);
        this.catchAll = bind(this.catchAll);
        this.user = Meteor.users.findOne({ username: this.name }, { fields: { username: 1 } });
        this.adapter = new RocketChatAdapter(this);

        new HubotScripts(this);

        console.log(`InternalHubotRobot initialized as '${ this.name }'`);
    }
    loadAdapter() { return false; }
    hear(regex, callback) { return super.hear(regex, Meteor.bindEnvironment(callback)); }
    respond(regex, callback) { return super.respond(regex, Meteor.bindEnvironment(callback)); }
    enter(callback) { return super.enter(Meteor.bindEnvironment(callback)); }
    leave(callback) { return super.leave(Meteor.bindEnvironment(callback)); }
    topic(callback) { return super.topic(Meteor.bindEnvironment(callback)); }
    error(callback) { return super.error(Meteor.bindEnvironment(callback)); }
    catchAll(callback) { return super.catchAll(Meteor.bindEnvironment(callback)); }
}

and

export class RocketChatAdapter extends Hubot.Adapter {
    constructor(robot) {
        super(robot);

        console.log('RocketChatAdapter initialized');
    }

    send(envelope, ...strings) {
        this.robot.logger.info('[ROBOT → adapter → send()]');
        // ...
    }

    // Many more overrides
}

The internal Hubot is initialized with InternalHubot = new InternalHubotRobot(RocketChat.settings.get('InternalHubot_Username'), 'Custom Alias'); and I see in the logs:

I20190318-11:28:59.866(1)? RocketChatAdapter initialized
I20190318-11:29:00.209(1)? [Mon Mar 18 2019 11:29:00 GMT+0100 (CET)] WARNING A script has tried registering a HTTP route while the HTTP server is disabled with --disabled-httpd.
I20190318-11:29:00.211(1)? Loaded help.coffee
I20190318-11:29:00.211(1)? InternalHubotRobot initialized as 'Custom Alias'

So both constructors are invoked properly. But all methods calls to robot's and adapter's methods are invoked on base classes from Hubot package, not from InternalHubotRobot / RocketChatAdapter.

And here's the problem: since those methods are not overriden / invoked as they should be, there is Fiber error and responses are not sent since default Hubot adapter's send() method does not do anything.

What I did:

  • I was able to get rid of Fiber error by wrapping like robot.respond /(help)+(?:\s+(.*))?$/i, Meteor.bindEnvironment((incomingMessage) (it's basically what InternalHubotRobot's constructor should do by wrapping methods with bind()
  • I was able to send response by overriding send through prototype:
    Hubot.Robot.prototype.send = function(envelope, ...args) {
        return sendHelper(this, envelope, args, (string) =>
            RocketChat.sendMessage(InternalHubot.user, { msg: string }, { _id: envelope.room })
        );
    };
    

However: it's dirty and I would like to rely on inheritance and method overriding in child class.

I'm not a JavaScript / Meteor / Rocket.Chat expert so maybe I'm missing something, a little detail. How can I achieve working inheritance?

Info about versions:

  • Rocket.Chat 0.73.1 / 0.74.3 (both with customized Internal Hubot, restored in our custom fork). On production we have 0.72.3 and there Internal Hubot is working properly
  • Hubot 3.3.1
  • Meteor 1.8.0.2
0

There are 0 best solutions below