{"action":"created","issue":{"url":"https://api.github.com/repos/OgarProject/Ogar/issues/588","repository_url":"https://api.github.com/repos/OgarProject/Ogar","labels_url":"https://api.github.com/repos/OgarProject/Ogar/issues/588/labels{/name}","comments_url":"https://api.github.com/repos/OgarProject/Ogar/issues/588/comments","events_url":"https://api.github.com/repos/OgarProject/Ogar/issues/588/events","html_url":"https://github.com/OgarProject/Ogar/issues/588","id":156141492,"number":588,"title":"New protocol fix for Ogar server","user":{"login":"Barbosik","id":19355276,"avatar_url":"https://avatars.githubusercontent.com/u/19355276?v=3","gravatar_id":"","url":"https://api.github.com/users/Barbosik","html_url":"https://github.com/Barbosik","followers_url":"https://api.github.com/users/Barbosik/followers","following_url":"https://api.github.com/users/Barbosik/following{/other_user}","gists_url":"https://api.github.com/users/Barbosik/gists{/gist_id}","starred_url":"https://api.github.com/users/Barbosik/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Barbosik/subscriptions","organizations_url":"https://api.github.com/users/Barbosik/orgs","repos_url":"https://api.github.com/users/Barbosik/repos","events_url":"https://api.github.com/users/Barbosik/events{/privacy}","received_events_url":"https://api.github.com/users/Barbosik/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":5,"created_at":"2016-05-22T08:30:53Z","updated_at":"2016-05-22T08:50:05Z","closed_at":null,"body":"Here is a fix for ogar server to support the new protocol. \r\nIt supports both protocols - 5 and 7. So you can connect with any client and it will works correctly.\r\n\r\nI'm used some old version of sources, so some parts in GameServer and PlayerTracker may be different.\r\n\r\nThe changes:\r\n\r\n**src\\GameServer.js:**\r\n\r\nOld:\r\n```\r\n    this.lb_packet = new ArrayBuffer(0);\r\n```\r\nNew:\r\n```\r\n    this.lb_packet5 = new ArrayBuffer(0); // Leaderboard packet for protocol 5\r\n    this.lb_packet6 = new ArrayBuffer(0); // Leaderboard packet for protocol 6\r\n```\r\n\r\nOld:\r\n```\r\n            this.lb_packet = new Packet.UpdateLeaderboard(this.leaderboard,this.gameMode.packetLB);\r\n```\r\nNew:\r\n```\r\n            this.lb_packet5 = new Packet.UpdateLeaderboard(5, this.leaderboard,this.gameMode.packetLB);\r\n            this.lb_packet6 = new Packet.UpdateLeaderboard(6, this.leaderboard,this.gameMode.packetLB);\r\n```\r\n\r\n**src\\PlayerTracker.js:**\r\n\r\nOld:\r\n```\r\nPlayerTracker.prototype.update = function() {\r\n// Actions buffer (So that people cant spam packets)\r\n    if (this.socket.packetHandler.pressSpace) { // Split cell\r\n```\r\nNew:\r\n```\r\nPlayerTracker.prototype.update = function() {\r\n    if (this.socket.packetHandler.protocol <= 0)  // if initialization is not complete yet then do not update\r\n        return;\r\n\r\n// Actions buffer (So that people cant spam packets)\r\n    if (this.socket.packetHandler.pressSpace) { // Split cell\r\n```\r\n\r\nOld:\r\n```\r\n        // Update leaderboard\r\n        if (this.tickLeaderboard <= 0) {\r\n            this.socket.sendPacket(this.gameServer.lb_packet);\r\n            this.tickLeaderboard = 10; // 20 ticks = 1 second\r\n        } else {\r\n            this.tickLeaderboard--;\r\n        }\r\n```\r\nNew:\r\n```\r\n    // Update leaderboard\r\n    if (this.tickLeaderboard <= 0) {\r\n        if (this.socket.packetHandler.protocol <= 5)\r\n            this.socket.sendPacket(this.gameServer.lb_packet5);\r\n        else \r\n            this.socket.sendPacket(this.gameServer.lb_packet6);\r\n        this.tickLeaderboard = 10; // 20 ticks = 1 second\r\n    } else {\r\n        this.tickLeaderboard--;\r\n    }\r\n```\r\n\r\n**src\\PacketHandler.js:**\r\n\r\nOld:\r\n```\r\n        case 0:\r\n            // Check for invalid packets\r\n            if ((view.byteLength + 1) % 2 == 1) {\r\n                break;\r\n            }\r\n\r\n            // Set Nickname\r\n            var nick = \"\";\r\n            var maxLen = this.gameServer.config.playerMaxNickLength * 2; // 2 bytes per char\r\n            for (var i = 1; i < view.byteLength && i <= maxLen; i += 2) {\r\n                var charCode = view.getUint16(i, true);\r\n                if (charCode == 0) {\r\n                    break;\r\n                }\r\n\r\n                nick += String.fromCharCode(charCode);\r\n            }\r\n            this.setNickname(nick);\r\n            break;\r\n```\r\nNew:\r\n```\r\n    switch (packetId) {\r\n        case 0:\r\n            var nick = \"\";\r\n            var bufferName = new Buffer(buffer);\r\n            bufferName = bufferName.slice(1);\r\n            if (bufferName[bufferName.length-1] == 0)                   // remove zero terminator (if exists)\r\n                bufferName = bufferName.slice(0, bufferName.length-1);\r\n\r\n\r\n            if (bufferName.length > 0) {\r\n                if (this.protocol <= 5) {\r\n                    // protocol 5-\r\n                    nick = bufferName.toString('ucs2');  // unicode => string\r\n                } else {\r\n                    // protocol 6+\r\n                    nick = bufferName.toString('utf8');  // utf8 => string\r\n                }\r\n            }\r\n            this.setNickname(nick);\r\n            break;\r\n```\r\n\r\nOld:\r\n```\r\n        case 255:\r\n            // Connection Start\r\n            if (view.byteLength == 5) {\r\n                this.protocol = view.getUint32(1, true);\r\n                // Send SetBorder packet first\r\n                var c = this.gameServer.config;\r\n                this.socket.sendPacket(new Packet.SetBorder(\r\n                    c.borderLeft + this.socket.playerTracker.scrambleX,\r\n                    c.borderRight + this.socket.playerTracker.scrambleX,\r\n                    c.borderTop + this.socket.playerTracker.scrambleY,\r\n                    c.borderBottom + this.socket.playerTracker.scrambleY\r\n                ));\r\n            }\r\n            break;\r\n```\r\nNew (please note that there is 254 instead of 255, it was a bug in Ogar server, so I fixed it):\r\n```\r\n        case 254:\r\n            // Connection Start \r\n            if (view.byteLength == 5) {\r\n                this.protocol = view.getUint32(1, true);\r\n                var c = this.gameServer.config;\r\n                this.socket.sendPacket(new Packet.ClearNodes());\r\n                this.socket.sendPacket(new Packet.SetBorder(\r\n                    c.borderLeft + this.socket.playerTracker.scrambleX,\r\n                    c.borderRight + this.socket.playerTracker.scrambleX,\r\n                    c.borderTop + this.socket.playerTracker.scrambleY,\r\n                    c.borderBottom + this.socket.playerTracker.scrambleY));\r\n            }\r\n            break;\r\n```\r\n\r\nOld:\r\n```\r\nPacketHandler.prototype.setNickname = function(newNick) {\r\n    var client = this.socket.playerTracker;\r\n    if (client.cells.length < 1) {\r\n        // Set name first\r\n        client.setName(newNick);\r\n\r\n        // If client has no cells... then spawn a player\r\n        this.gameServer.gameMode.onPlayerSpawn(this.gameServer, client);\r\n\r\n        // Turn off spectate mode\r\n        client.spectate = false;\r\n    }\r\n};\r\n```\r\nNew:\r\n```\r\nPacketHandler.prototype.setNickname = function(newNick) {\r\n    var client = this.socket.playerTracker;\r\n    if (client.cells.length < 1) {\r\n        // Set name first\r\n        client.setName(newNick); \r\n\r\n        var c = this.gameServer.config;\r\n        this.socket.sendPacket(new Packet.ClearNodes());\r\n        this.socket.sendPacket(new Packet.SetBorder(\r\n            c.borderLeft + this.socket.playerTracker.scrambleX,\r\n            c.borderRight + this.socket.playerTracker.scrambleX,\r\n            c.borderTop + this.socket.playerTracker.scrambleY,\r\n            c.borderBottom + this.socket.playerTracker.scrambleY));\r\n\r\n        // If client has no cells... then spawn a player\r\n        this.gameServer.gameMode.onPlayerSpawn(this.gameServer,client);\r\n\r\n        // Turn off spectate mode\r\n        client.spectate = false;\r\n    }\r\n};\r\n```\r\n\r\n**src\\packet\\ClearNodes.js:**\r\n\r\nJust replace file with the following content::\r\n```\r\nfunction ClearNodes() {}\r\n\r\nmodule.exports = ClearNodes;\r\n\r\nClearNodes.prototype.build = function() {\r\n    var buf = new ArrayBuffer(1);\r\n    var view = new DataView(buf);\r\n\r\n    view.setUint8(0, 18, true);\r\n\r\n    return buf;\r\n};\r\n```\r\n\r\n**src\\packet\\UpdateLeaderboard.js**\r\n\r\nJust replace file with the following content::\r\n```\r\nfunction UpdateLeaderboard(protocol, leaderboard, packetLB) {\r\n    this.protocol = protocol;\r\n    this.leaderboard = leaderboard;\r\n    this.packetLB = packetLB;\r\n}\r\n\r\nmodule.exports = UpdateLeaderboard;\r\n\r\nUpdateLeaderboard.prototype.build = function() {\r\n    var lb = this.leaderboard;\r\n    switch (this.packetLB) {\r\n\r\n\r\n        case 48: // Custom Text List?\r\n            {\r\n                var offset = 0;\r\n                var buffer = new Buffer(0x10000);\r\n\r\n\r\n                buffer.writeUInt8(48, offset);\r\n                offset++;\r\n\r\n                var countOffset = offset;\r\n                offset += 4;\r\n\r\n\r\n                var count = 0;\r\n\r\n                for (var i = 0; i < lb.length; i++) {\r\n                    if (typeof lb[i] == \"undefined\")\r\n                        continue;\r\n                    var item = lb[i];\r\n\r\n                    var name = item;\r\n                    name = name ? name : \"\";\r\n\r\n\r\n                    buffer.writeUInt32LE(0, offset);\r\n                    offset += 4;\r\n\r\n\r\n                    if (this.protocol <= 5)\r\n                        offset += buffer.write(name, offset, 'ucs2');   // string => unicode\r\n                    else\r\n                        offset += buffer.write(name, offset);           // string => utf8\r\n                    buffer.writeUInt8(0, offset);                       // string zero terminator\r\n                    offset++;\r\n    \r\n                    count++;\r\n                }\r\n                buffer.writeUInt32LE(count, countOffset);               // Number of elements\r\n                return buffer.slice(0, offset);\r\n            }\r\n            break;\r\n\r\n        case 49: // FFA\r\n            {\r\n                var offset = 0;\r\n                var buffer = new Buffer(0x10000);\r\n    \r\n                buffer.writeUInt8(49, offset);                        // Packet ID\r\n                offset+=1;\r\n    \r\n    \r\n                var countOffset = offset;\r\n                offset += 4;\r\n    \r\n                var count = 0;\r\n                for (var i = 0; i < lb.length; i++) {\r\n                    if (typeof lb[i] == \"undefined\")\r\n                        continue;\r\n                    var item = lb[i];\r\n                                                                        \r\n                    var isMe = false;                                   // 1 for red color (current player), 0 for white color (other players)\r\n                    var name = item.getName();\r\n                    name = name ? name : \"\";\r\n    \r\n    \r\n                    // Write record\r\n                    buffer.writeUInt32LE(isMe ? 1:0, offset);           // isMe flag (previously cell ID)\r\n                    offset += 4;\r\n    \r\n                    if (this.protocol <= 5)\r\n                        offset += buffer.write(name, offset, 'ucs2');   // string => unicode\r\n                    else\r\n                        offset += buffer.write(name, offset);           // string => utf8\r\n                    buffer.writeUInt8(0, offset);                       // string zero terminator\r\n                    offset += 1;\r\n    \r\n                    count++;\r\n                }\r\n                buffer.writeUInt32LE(count, countOffset);               // Number of elements\r\n                return buffer.slice(0, offset);\r\n            }  \r\n            break;\r\n\r\n        case 50: // (Team) Leaderboard Update\r\n            {\r\n                var offset = 0;\r\n                var buffer = new Buffer(0x10000);\r\n    \r\n                buffer.writeUInt8(50, offset);                          // Packet ID\r\n                offset++;\r\n    \r\n                var countOffset = offset;\r\n                offset += 4;\r\n    \r\n                var count = 0;\r\n                for (var i = 0; i < lb.length; i++) {\r\n    \r\n                    var value = lb[i];\r\n    \r\n                    // little validation\r\n                    value = value < 0 ? 0 : value;\r\n                    value = value > 1 ? 1 : value;\r\n    \r\n                    buffer.writeFloatLE(0, offset);                       // string zero terminator\r\n                    offset += 4;\r\n                }\r\n                buffer.writeUInt32LE(count, countOffset);               // Number of elements\r\n                return buffer.slice(0, offset);\r\n            }\r\n            break;\r\n\r\n        default:\r\n            break;\r\n    }\r\n};\r\n```\r\n\r\n**src\\packet\\UpdateNodes.js**: \r\n\r\nThe main change, just replace file with the following content:\r\n```\r\nfunction UpdateNodes(protocol, destroyQueue, nodes, nonVisibleNodes, scrambleX, scrambleY) {\r\n    this.protocol = protocol;\r\n    this.destroyQueue = destroyQueue;\r\n    this.nodes = nodes;\r\n    this.nonVisibleNodes = nonVisibleNodes;\r\n    this.scrambleX = scrambleX;\r\n    this.scrambleY = scrambleY;\r\n}\r\n\r\nmodule.exports = UpdateNodes;\r\n\r\nUpdateNodes.prototype.build = function() {\r\n    if (this.protocol <= 5) { \r\n        // protocol 5\r\n        \r\n        // Calculate nodes sub packet size before making the data view\r\n        var nodesLength = 0;\r\n        for (var i = 0; i < this.nodes.length; i++) {\r\n            var node = this.nodes[i];\r\n    \r\n            if (typeof node == \"undefined\") {\r\n                continue;\r\n            }\r\n    \r\n            nodesLength = nodesLength + 20 + (node.getName().length * 2);\r\n        }\r\n    \r\n        var buf = new ArrayBuffer(3 + (this.destroyQueue.length * 12) + (this.nonVisibleNodes.length * 4) + nodesLength + 8);\r\n        var view = new DataView(buf);\r\n    \r\n        view.setUint8(0, 16, true); // Packet ID\r\n        view.setUint16(1, this.destroyQueue.length, true); // Nodes to be destroyed\r\n    \r\n        var offset = 3;\r\n        for (var i = 0; i < this.destroyQueue.length; i++) {\r\n            var node = this.destroyQueue[i];\r\n    \r\n            if (!node) {\r\n                continue;\r\n            }\r\n    \r\n            var killer = 0;\r\n            if (node.getKiller()) {\r\n                killer = node.getKiller().nodeId;\r\n            }\r\n    \r\n            view.setUint32(offset, killer, true); // Killer ID\r\n            view.setUint32(offset + 4, node.nodeId, true); // Node ID\r\n    \r\n            offset += 8;\r\n        }\r\n    \r\n        for (var i = 0; i < this.nodes.length; i++) {\r\n            var node = this.nodes[i];\r\n    \r\n            if (typeof node == \"undefined\") {\r\n                continue;\r\n            }\r\n    \r\n            view.setUint32(offset, node.nodeId, true); // Node ID\r\n            view.setInt32(offset + 4, node.position.x + this.scrambleX, true); // X position\r\n            view.setInt32(offset + 8, node.position.y + this.scrambleY, true); // Y position\r\n            view.setInt16(offset + 12, node.getSize(), true); // Mass formula: Radius (size) = (mass * mass) / 100\r\n            view.setUint8(offset + 14, node.color.r, true); // Color (R)\r\n            view.setUint8(offset + 15, node.color.g, true); // Color (G)\r\n            view.setUint8(offset + 16, node.color.b, true); // Color (B)\r\n            view.setUint8(offset + 17, node.spiked, true); // Flags\r\n            offset += 18;\r\n    \r\n            var name = node.getName();\r\n            if (name) {\r\n                for (var j = 0; j < name.length; j++) {\r\n                    var c = name.charCodeAt(j);\r\n                    if (c){\r\n                        view.setUint16(offset, c, true);\r\n                    }\r\n                    offset += 2;\r\n                }\r\n            }\r\n    \r\n            view.setUint16(offset, 0, true); // End of string\r\n            offset += 2;\r\n        }\r\n    \r\n        var len = this.nonVisibleNodes.length + this.destroyQueue.length;\r\n        view.setUint32(offset, 0, true); // End\r\n        view.setUint32(offset + 4, len, true); // # of non-visible nodes to destroy\r\n    \r\n        offset += 8;\r\n    \r\n        // Destroy queue + nonvisible nodes\r\n        for (var i = 0; i < this.destroyQueue.length; i++) {\r\n            var node = this.destroyQueue[i];\r\n    \r\n            if (!node) {\r\n                continue;\r\n            }\r\n    \r\n            view.setUint32(offset, node.nodeId, true);\r\n            offset += 4;\r\n        }\r\n        for (var i = 0; i < this.nonVisibleNodes.length; i++) {\r\n            var node = this.nonVisibleNodes[i];\r\n    \r\n            if (!node) {\r\n                continue;\r\n            }\r\n    \r\n            view.setUint32(offset, node.nodeId, true);\r\n            offset += 4;\r\n        }\r\n    \r\n        return buf;\r\n    } else {\r\n        // protocol 6+\r\n        var buffer = new Buffer(0x10000);\r\n        var offset = 0;\r\n\r\n        buffer.writeUInt8(0x10, offset);                      // Packet ID\r\n        offset++;\r\n\r\n        // Eat Records\r\n        var eatCountOffset = offset;\t\t// actual count will be written late\r\n        offset += 2;                            // temporary skip count field\r\n \r\n        var eatCount = 0;\r\n        for (var i = 0; i < this.destroyQueue.length; i++) {\r\n            var node = this.destroyQueue[i];\r\n\r\n            if (!node) {\r\n                continue;\r\n            }\r\n\r\n            var killer = 0;\r\n            if (node.getKiller()) {\r\n                killer = node.getKiller().nodeId;\r\n            }\r\n\r\n            buffer.writeUInt32LE(killer, offset);\t// Hunter ID\r\n            offset+=4;\r\n            buffer.writeUInt32LE(node.nodeId, offset);  // Prey ID\r\n            offset+=4;\r\n\r\n            eatCount++; \r\n        }\r\n        buffer.writeUInt16LE(eatCount, eatCountOffset);\t// eat record count\r\n\r\n\r\n        // Update Records\r\n        for (var i = 0; i < this.nodes.length; i++) {\r\n            var node = this.nodes[i];\r\n            if (typeof node == \"undefined\")\r\n                continue;\r\n\r\n            var cellId = node.nodeId;\r\n            var cellX = node.position.x + this.scrambleX;\r\n            var cellY = node.position.y + this.scrambleY;\r\n            var cellSize = node.getSize();\r\n            var cellColorR = node.color.r;\r\n            var cellColorG = node.color.g;\r\n            var cellColorB = node.color.b;\r\n            var skinName = null;\r\n            var cellName = node.getName();\r\n            var isVirus = (node.spiked & 0x01) != 0;\r\n            var isColorPresent = true;             // we always include color\r\n            var isSkinPresent = skinName != null && skinName.length > 0;\r\n            var isNamePresent = cellName != null;\r\n            var isAgitated = false;                // true = high wave amplitude on a cell outline\r\n\r\n            // A little validation\r\n            if (cellId==0) {\r\n                console.log(\"error cell id==0 is not valid value!\");\r\n                continue;\r\n            }\r\n\r\n            // Write update record\r\n            buffer.writeUInt32LE(cellId, offset);                             // Cell ID\r\n            offset += 4;\r\n            buffer.writeInt32LE(cellX, offset);                               // Coordinate X\r\n            offset += 4;\r\n            buffer.writeInt32LE(cellY, offset);                               // Coordinate Y\r\n            offset += 4;\r\n            buffer.writeUInt16LE(cellSize, offset);                           // Cell Size (not to be confused with mass, because mass = size*size/100)\r\n            offset += 2;\r\n\r\n            var flags = 0;\r\n            if (isVirus)\r\n                flags += 1;\r\n            if (isColorPresent)\r\n                flags += 2;\r\n            if (isSkinPresent)\r\n                flags += 4;\r\n            if (isNamePresent)\r\n                flags += 8;\r\n            if (isAgitated)\r\n                flags += 16;\r\n            buffer.writeUInt8(flags, offset);                                 // Flags\r\n            offset++;\r\n\r\n            if (isColorPresent) {\r\n                buffer.writeUInt8(cellColorR, offset);                        // Color R\r\n                offset++;                                                     \r\n                buffer.writeUInt8(cellColorG, offset);                        // Color G\r\n                offset++;\r\n                buffer.writeUInt8(cellColorB, offset);                        // Color B\r\n                offset++;\r\n            }\r\n            if (isSkinPresent) {\r\n                offset += buffer.write(skinName, offset);                     // Skin Name in UTF8\r\n                buffer.writeUInt8(0, offset);                                 // Zero-terminator\r\n                offset++;\r\n            }\r\n            if (isNamePresent) {\r\n                offset += buffer.write(cellName, offset);                     // Cell Name in UTF8\r\n                buffer.writeUInt8(0, offset);                                 // Zero-terminator\r\n                offset++;\r\n            }\r\n        }\r\n        buffer.writeUInt32LE(0, offset);                                      // Cell Update record terminator\r\n        offset += 4;\r\n\r\n\r\n        // Remove Records\r\n        var removeCountOffset = offset;          // actual count will be written late\r\n        offset += 2;                             // temporary skip count field\r\n\r\n        var removeCount = 0;\r\n        for (var i = 0; i < this.destroyQueue.length; i++) {\r\n            var node = this.destroyQueue[i];\r\n            if (!node)\r\n                continue;\r\n\r\n            buffer.writeUInt32LE(node.nodeId, offset);                        // Cell ID\r\n            offset += 4;\r\n            removeCount++;\r\n        }\r\n        for (var i = 0; i < this.nonVisibleNodes.length; i++) {\r\n            var node = this.nonVisibleNodes[i];\r\n            if (!node) \r\n                continue;\r\n\r\n            buffer.writeUInt32LE(node.nodeId, offset);                        // Cell ID\r\n            offset += 4;\r\n            removeCount++;\r\n        }\r\n        buffer.writeUInt16LE(removeCount, removeCountOffset);                           // Eat Record Count\r\n\r\n        return buffer.slice(0, offset);\r\n    }\r\n};\r\n```\r\n\r\nMay be I forgot to mention some change, because I didn't saved previous version and my version was not the latest, so I find changes from memory.\r\n\r\nI tested it with the latest agario client and at a glance it works good. It also works with alternative clients. There is no need to change something. It will automatically detect which protocol should be used.\r\n\r\nActually javascript is not my language, so something may be written is not so good. But at least it works :)\r\nAsk me if it didn't works for you.\r\n\r\nEnjoy and have fun! :)"},"comment":{"url":"https://api.github.com/repos/OgarProject/Ogar/issues/comments/220821230","html_url":"https://github.com/OgarProject/Ogar/issues/588#issuecomment-220821230","issue_url":"https://api.github.com/repos/OgarProject/Ogar/issues/588","id":220821230,"user":{"login":"dl8sd11","id":19171021,"avatar_url":"https://avatars.githubusercontent.com/u/19171021?v=3","gravatar_id":"","url":"https://api.github.com/users/dl8sd11","html_url":"https://github.com/dl8sd11","followers_url":"https://api.github.com/users/dl8sd11/followers","following_url":"https://api.github.com/users/dl8sd11/following{/other_user}","gists_url":"https://api.github.com/users/dl8sd11/gists{/gist_id}","starred_url":"https://api.github.com/users/dl8sd11/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dl8sd11/subscriptions","organizations_url":"https://api.github.com/users/dl8sd11/orgs","repos_url":"https://api.github.com/users/dl8sd11/repos","events_url":"https://api.github.com/users/dl8sd11/events{/privacy}","received_events_url":"https://api.github.com/users/dl8sd11/received_events","type":"User","site_admin":false},"created_at":"2016-05-22T08:50:05Z","updated_at":"2016-05-22T08:50:05Z","body":"Can you upload these js file, please?\r\nI can't really find the codes in the old file."}}
{"actor":{"display_login":"dl8sd11"}}