(Tautulli) Webhook and JSON issues

Description

Hello Rocket.Chat forum,
I’m not sure where to begin, so I hope this is the right place.
Google wasn’t really helpful, I only found:

I’m also new at JSON data, but I tried using https://jsonlint.com/ to validate it, which hasn’t failed. So I’m thinking it’s the script, but I can’t tell :confused:

I’m trying to send a webook from Tautulli to Rocket.Chat, from what I can tell, it’s correctly set up. I’ll show down in aditional information what has been setup.

I’m new at this, so I think I’ve done it the wrong way, but I can’t tell.
I’ve tried enabling all the logging, but it doesn’t pick anything up about the webhook from what I can tell.
Any ideas where to start, or even know how to make it work?

Server Setup Information

  • Version of Rocket.Chat Server: 3.17.0
  • Operating System: Ubuntu Server 20.04
  • Deployment Method: Running on a VM
  • Number of Running Instances: 1
  • DB Replicaset Oplog: I’m not sure where to find it.
  • NodeJS Version: v12.22.4
  • MongoDB Version: v4.4.8
  • Proxy: NPM (Nginx with Let’s Encrypt)
  • Firewalls involved: UFW (disabled atm.)

Any additional Information

I’ve set it up following this guide, except from step 6 and afterwards:

The script I’m using is the one I found here: Integrations - Rocket.Chat Docs

/* exported Script */
/* globals console, _, s, HTTP */

/** Global Helpers
 *
 * console - A normal console instance
 * _       - An underscore instance
 * s       - An underscore string instance
 * HTTP    - The Meteor HTTP object to do sync http calls
 */

class Script {
  /**
   * @params {object} request
   */
  prepare_outgoing_request({ request }) {
    // request.params            {object}
    // request.method            {string}
    // request.url               {string}
    // request.auth              {string}
    // request.headers           {object}
    // request.data.token        {string}
    // request.data.channel_id   {string}
    // request.data.channel_name {string}
    // request.data.timestamp    {date}
    // request.data.user_id      {string}
    // request.data.user_name    {string}
    // request.data.text         {string}
    // request.data.trigger_word {string}

    let match;

    // Change the URL and method of the request
    match = request.data.text.match(/^pr\s(ls|list)/);
    if (match) {
      return {
        url: request.url + "/pulls",
        headers: request.headers,
        method: "GET",
      };
    }

    // Prevent the request and return a new message
    match = request.data.text.match(/^help$/);
    if (match) {
      return {
        message: {
          text: [
            "**commands**",
            "```",
            "  pr ls [open|closed|all]  List Pull Requests",
            "```",
          ].join("\n"),
          // "channel": "#name-of-channel",
          // "attachments": [{
          //   "color": "#FF0000",
          //   "author_name": "Rocket.Cat",
          //   "author_link": "open.rocket.chat/direct/rocket.cat",
          //   "author_icon": "open.rocket.chat/avatar/rocket.cat.jpg",
          //   "title": "Rocket.Chat",
          //   "title_link": "rocket.chat",
          //   "text": "Rocket.Chat, the best open source chat",
          //   "fields": [{
          //     "title": "Priority",
          //     "value": "High",
          //     "short": false
          //   }],
          //   "image_url": "rocket.chat/images/mockup.png",
          //   "thumb_url": "rocket.chat/images/mockup.png"
          // }]
        },
      };
    }
  }

  /**
   * @params {object} request, response
   */
  process_outgoing_response({ request, response }) {
    // request              {object} - the object returned by prepare_outgoing_request

    // response.error       {object}
    // response.status_code {integer}
    // response.content     {object}
    // response.content_raw {string/object}
    // response.headers     {object}

    var text = [];
    response.content.forEach(function (pr) {
      text.push(
        "> " +
          pr.state +
          " [#" +
          pr.number +
          "](" +
          pr.html_url +
          ") - " +
          pr.title
      );
    });

    // Return false will abort the response
    // return false;

    // Return empty will proceed with the default response process
    // return;

    return {
      content: {
        text: text.join("\n"),
        parseUrls: false,
        // "attachments": [{
        //   "color": "#FF0000",
        //   "author_name": "Rocket.Cat",
        //   "author_link": "open.rocket.chat/direct/rocket.cat",
        //   "author_icon": "open.rocket.chat/avatar/rocket.cat.jpg",
        //   "title": "Rocket.Chat",
        //   "title_link": "rocket.chat",
        //   "text": "Rocket.Chat, the best open source chat",
        //   "fields": [{
        //     "title": "Priority",
        //     "value": "High",
        //     "short": false
        //   }],
        //   "image_url": "rocket.chat/images/mockup.png",
        //   "thumb_url": "rocket.chat/images/mockup.png"
        // }]
      },
    };
  }
}

The Webhook URL is (without the exact info):

http://192.168.X.X:3000/hooks/YXYZ

The Curl is:

curl -X POST -H 'Content-Type: application/json' --data \
'{
  "text": "Example message",
  "attachments": [
    {
      "title": "Rocket.Chat",
      "title_link": "rocket.chat",
      "text": "Rocket.Chat, the best open source chat",
      "image_url": "/images/integration-attachment-example.png",
      "color": "#764FA5"
    }
  ]
}' http://192.168.X.X:3000/hooks/YXYZ

The JSON headers in Tautulli is:

Content-Type: application/json 
Accept: application/json

The JSON Data int Tautulli and the example payload in Rocket.Chat is:

{
  "text": "Example message",
  "attachments": [
    {
      "title": "Rocket.Chat",
      "title_link": "rocket.chat",
      "text": "Rocket.Chat, the best open source chat",
      "image_url": "/images/integration-attachment-example.png",
      "color": "#764FA5"
    }
  ]
}

Hey Nanobug! :wave:

This caught my eye. The IP here looks like it’s a private IP. Are you sure your rocketchat instance is accessible from the tautulli server :thinking: ?

Same thing, you sure your tautulli instance is on the same subnet as your rocketchat instance? Can you check your tautulli logs about any failed POST attempts?

EDIT - You’re also using the outgoing webhook example script instead of the incoming webhook example script (you can find both in the same page you got the above script from). They’re different. The incoming webhook script (what you’re trying to set up) implements the method process_incoming_request, which is not present in your script. I’m positive that this is the reason nothings showing up in the logs (unless the answer to both of my previous questions is “no”). The data that’s being sent from the other application, isn’t getting processed at all.

I’ve also reformatted & updated the post with all the links you provided in the other posts :slight_smile:

Thanks for being so verbose :wink:

This caught my eye. The IP here looks like it’s a private IP. Are you sure your rocketchat instance is accessible from the tautulli server :thinking: ?

I’m not sure it accessible, but it’s 100 % on the same subnet, that’s where I run all of my services on my servers, and everything has it’s own IP as well.

I thought I’d test it locally first, but I access tautulli through a subdomain, so that needs to be change.

  • I’ve changed it to:
https://rocket.my.domain/hooks/XYZ

Same thing, you sure your tautulli instance is on the same subnet as your rocketchat instance? Can you check your tautulli logs about any failed POST attempts?

It’s 100 % on the same subnet.
The log:

You’re also using the outgoing webhook example script instead of the incoming webhook example script (you can find both in the same page you got the above script from). They’re different. The incoming webhook script (what you’re trying to set up) implements the method process_incoming_request , which is not present in your script. I’m positive that this is the reason nothings showing up in the logs (unless the answer to both of my previous questions is “no”). The data that’s being sent from the other application, isn’t getting processed at all.

I changed it to

/* exported Script */
/* globals console, _, s */

/** Global Helpers
 *
 * console - A normal console instance
 * _       - An underscore instance
 * s       - An underscore string instance
 */

class Script {
  /**
   * @params {object} request
   */
  process_incoming_request({ request }) {
    // request.url.hash
    // request.url.search
    // request.url.query
    // request.url.pathname
    // request.url.path
    // request.url_raw
    // request.url_params
    // request.headers
    // request.user._id
    // request.user.name
    // request.user.username
    // request.content_raw
    // request.content

    // console is a global helper to improve debug
    console.log(request.content);

    return {
      content:{
        text: request.content.text
        // "attachments": [{
        //   "color": "#FF0000",
        //   "author_name": "Rocket.Cat",
        //   "author_link": "https://open.rocket.chat/direct/rocket.cat",
        //   "author_icon": "https://open.rocket.chat/avatar/rocket.cat.jpg",
        //   "title": "Rocket.Chat",
        //   "title_link": "https://rocket.chat",
        //   "text": "Rocket.Chat, the best open source chat",
        //   "fields": [{
        //     "title": "Priority",
        //     "value": "High",
        //     "short": false
        //   }],
        //   "image_url": "https://rocket.chat/images/mockup.png",
        //   "thumb_url": "https://rocket.chat/images/mockup.png"
        // }]
       }
    };

    // return {
    //   error: {
    //     success: false,
    //     message: 'Error example'
    //   }
    // };
  }
}

I think it got confused or missed the incoming one.

I’ve also reformatted & updated the post with all the links you provided in the other posts :slight_smile:

Thank you :slight_smile:

Thanks for being so verbose :wink:

I’ve learned that you might as well try first yourself, and then provide all the information you possibly can at after trying yourself, instead of filling it out as you go.

EDIT:
The formatting of the script didn’t go well…