Цикл JavaScript для размещения отфильтрованного массива объектов, полученных из webhook - PullRequest
0 голосов
/ 08 января 2019

Цель

Захватите каждое событие, отправленное через веб-крючок, и превратите его в сообщение Slack. События включают в себя новые сообщения в блоге, вопросы, обсуждения, вики-страницу и т. Д. (Квалифицированные как contents) и комментарии (квалифицированные как comments), размещенные в онлайн-сообществе. Иногда несколько событий отправляются в webhook одновременно .

Попытка метода

Эта простая функция JavaScript Azure предназначена для

  • Получение одного или нескольких событий webhook, отправленных в массиве JSON
  • Фильтровать объекты, квалифицированные как contents, из объектов, квалифицированных как comments
  • Отправка запроса API для каждого объекта content и / или comment (оба имеют свою конечную точку URL)
  • Анализ каждого возвращаемого объекта (contents и comments возвращают похожую, но отличающуюся иерархию ключей)
  • Соберите значения в объекты JSON (по одному на событие, независимо от того, content или comment) и отправьте в Slack

Результаты

Следующий код работал нормально для single события webhook, пока я не попытался добавить цикл for для размещения нескольких событий webhook, отправленных в одном массиве.

Код

Пример JSON из webhook

{
    "events": [{
            "TypeId": "9999-999e",
            "DateOccurred": "2018-12-15T20:39:42.2487557Z",
            "EventData": {
                "ActorUserId": 1234,
                "ContentId": "5678-999c",
                "ContentTypeId": "9012-999d",
                "WikiPageId": 3456,
                "WikiId": 1
            }
        },
        {
            "TypeId": "1111-111f",
            "DateOccurred": "2018-12-15T22:55:37.7846546Z",
            "EventData": {
                "ActorUserId": 2345,
                "ContentId": "2222-222b",
                "ContentTypeId": "3333-333a",
                "ForumReplyId": 4567,
                "ForumThreadId": 8901,
                "ForumId": 2
            }
        },
        {
            "TypeId": "9012-888f",
            "DateOccurred": "2018-12-15T22:44:57.7091846Z",
            "EventData": {
                "ActorUserId": 9876,
                "CommentId": "8900-123a"
            }
        }
    ]
}

Пример JSON, возвращенный из запроса API

Несколько иная структура иерархий является точной.

(для содержания)

{
    "Content": {
        "CreatedByUser": {
            "ProfileUrl": "https://<company>.telligenthosting.net/members/<user>",
            "Username": "<user>"
        },
        "HtmlName": "Title",
        "HtmlDescription": "Text",
        "Url": "https://<company>.telligenthosting.net/<link>"
    }
}

(для комментариев)

{
    "Comment": {
        "Content": {
            "CreatedByUser": {
                "ProfileUrl": "https://<company>.telligenthosting.net/members/<user>",
                "Username": "<user>"
            },
            "HtmlName": "Title",
            "HtmlDescription": "Text",
            "Url": "https://<company>.telligenthosting.net/<link>"
        }
    }
}

Файл JavaScript (как функция Azure)

module.exports = function (context, data) {
    var json = data.body;

    var request = require('request');

    // Parse the webhook event JSON body

    var unparsed = JSON.stringify(json.events);
    var parsed = JSON.parse(unparsed);

    console.log(parsed) // RESULTS ARE AS EXPECTED (the JSON nested beneath `events`, beginning and ending with `[]`)

    for (var i = 0; i < parsed.length; i++) {

        // Parse out Id of webhook event (for all content types but comments)

        // This Id retrieves details about the content

        var ContentId, ContentTypeId;
        if (parsed[i].EventData.hasOwnProperty('ContentId')) {

            var ContentId = parsed[i].EventData.ContentId;
            var ContentTypeId = parsed[i].EventData.ContentTypeId;

            console.log(ContentTypeId); // RESULTS ARE NOT AS EXPECTED: Prints the same Id twice

            var options = {
                url: "https://<company>.telligenthosting.net/api.ashx/v2/genericcontent/" + ContentId + "/" + ContentTypeId + ".json",
                headers: {
                    "Rest-User-Token": "<token>",
                    "Content-Type": "application/json"
                }
            };
        };

        // Parse out Id of a webhook event (for comments only)

        // This Id retrieves details about a comment    

        var CommentId;
        if (parsed[i].EventData.hasOwnProperty('CommentId')) {

            var CommentId = parsed[i].EventData.CommentId;

            var options = {
                url: "https://<company>.telligenthosting.net/api.ashx/v2/comments/" + CommentId + ".json",
                headers: {
                    "Rest-User-Token": "<token>",
                    "Content-Type": "application/json"
                }
            };
        };

        function callback(error, response, body) {
            if (!error && response.statusCode == 200) {
                var info = JSON.parse(body);

                //For all content types but comments

                var username, profileUrl, subject, url, text;
                if (info.hasOwnProperty('Content')) {

                    username = info.Content.CreatedByUser.Username;
                    profileUrl = info.Content.CreatedByUser.ProfileUrl;
                    subject = info.Content.HtmlName;
                    url = info.Content.Url;
                    text = info.Content.HtmlDescription;
                };

                //For comments

                if (info.hasOwnProperty('Comment')) {

                    username = info.Comment.User.DisplayName;
                    profileUrl = info.Comment.User.ProfileUrl;
                    subject = info.Comment.Content.HtmlName;
                    url = info.Comment.Url;
                    text = info.Comment.Body;
                };
            };

            //Send to Slack

            function sendToSlack(theUsername, theIconEmoji) {

                var theUsername = "Bot";
                var theIconEmoji = ":bot:";

                var payload = {
                    attachments: [{
                        author_name: username,
                        author_link: profileUrl,
                        title: subject,
                        title_link: url,
                        text: text
                    }]
                };
                if (theUsername !== undefined) {
                    payload.username = theUsername;
                }
                if (theIconEmoji !== undefined) {
                    payload.icon_emoji = theIconEmoji;
                }
                var theRequest = {
                    url: urlWebHook,
                    method: "POST",
                    json: payload
                };
                request(theRequest, function (error, response, body) {});
            }

            var urlWebHook = "https://hooks.slack.com/services/<Id>";

            sendToSlack();
        };
    };
    request(options, callback);
};

Выпуск

Как отмечено в приведенном выше коде, похоже, что цикл проходит не каждое событие, а несколько раз первое событие.

Многое из того, что я прочитал, указывает на то, что for (var i = 0; i < json.length; i++) { - правильный подход, но независимо от того, что я пробую, функция Azure выдает 500 Internal Service Error и, в конце концов, время ожидания истекает. В консоли отладки информация не отображается, даже если включено подробное ведение журнала.

Спасибо

Спасибо за любой совет или образование.

Ответы [ 2 ]

0 голосов
/ 08 января 2019

EventData не определено, потому что вы неправильно строите свой объект.

Вот как вы можете это сделать:

var json = require("./test.json");

var unparsedEvents = json.events;
for (let event of unparsedEvents) {
    var ContentId = event.EventData.ContentId;
    var ContentTypeId = event.EventData.ContentTypeId;
    var CommentId = event.EventData.CommentId;
    var options = new Object();

    console.log("ContentId:", ContentId);
    console.log("ContentTypeId:", ContentTypeId);
    console.log("CommentId:", CommentId);

    if (CommentId) {
        options.url = "https://<company>.telligenthosting.net/api.ashx/v2/comments/" + CommentId + ".json";
        options.headers = {
            "Rest-User-Token": "<token>",
            "Content-Type": "application/json",
        };
    } else {
        options.url = "https://<company>.telligenthosting.net/api.ashx/v2/genericcontent/" + ContentId + "/" + ContentTypeId + ".json";
        options.headers = {
            "Rest-User-Token": "<token>",
            "Content-Type": "application/json",
        };
    }

    console.log("options:", options);
    console.log();
}
0 голосов
/ 08 января 2019

Я считаю, что вам нужно изменить parsed [0] на parsed [i]. В настоящее время вы просматриваете массив, но получаете доступ только к первому элементу, поэтому вы видите первое событие несколько раз.

...