{"id":5059,"date":"2023-05-09T23:35:00","date_gmt":"2023-05-10T04:35:00","guid":{"rendered":"https:\/\/www.incredigeek.com\/home\/?p=5059"},"modified":"2023-06-16T15:11:00","modified_gmt":"2023-06-16T20:11:00","slug":"voxer-bot-attempts-1-of-3","status":"publish","type":"post","link":"https:\/\/www.incredigeek.com\/home\/voxer-bot-attempts-1-of-3\/","title":{"rendered":"Voxer Bot Attempts"},"content":{"rendered":"\n<p>The following are various notes and findings on trying to create a &#8220;Bot&#8221; for Voxer.  Voxer doesn&#8217;t really have any options for web hooks, and the SDK is still in beta.  We&#8217;ll be exploring sending messages to a channel, how to use Curl or Fetch to send messages.  Unfortunately, signing in does not appear to be easy to automate.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Looking at Voxer<\/h2>\n\n\n\n<p>Voxer is primarily used via the modile apps, but there is also a web version at web.voxer.com<\/p>\n\n\n\n<p>Using Firefox, we can play with the Web Tools to get a better idea of what is going on.<\/p>\n\n\n\n<p>All the Javascript is easily readable.  api.js is of interest.  This can helps us understand how messages are sent.<\/p>\n\n\n\n<p>The Web interface seems to be somewhat buggy, could be it just doesn&#8217;t like going through burp, but had better luck monitoring the channel for new messages from a phone.<\/p>\n\n\n\n<p>Proxying the traffic through Burp is tricky.  The log in does not appear to work while the proxy is active, but you can log in, and then activate the proxy to capture and replay sending messages.  <\/p>\n\n\n\n<p>If you get &#8220;Voxer is open in another tab. Please click &#8216;OK&#8217; then close this tab.&#8221; clear all voxer cookies and log in again.  Seems to happen quite often.<\/p>\n\n\n\n<p>Interestingly, if you send a message, then send that message POST request to Repeater, change the text and resubmit it, it &#8220;Updates&#8221; the text of the message.  So if you know the message_id, or maybe the create_time, you can change the text in messages.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">About Sending Messages<\/h2>\n\n\n\n<p>When you send a message, there are 2 POST requests sent.  The first one sends the message and the second one consumes the message.  It looks like you really only need the first post message request to actually send messages.  Think the consume message post is for the browser to trigger a refresh on the messages in the message list.<\/p>\n\n\n\n<p>There are two variables that change message to message<\/p>\n\n\n\n<p>message_id and create_time<\/p>\n\n\n\n<p>Looking into the api.js file we see that create_time is done with the following code<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">now = new Date().getTime() \/ 1000,<\/pre>\n\n\n\n<p>And here is the code used to generate the message_id.  First part is the time, the next part is random.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">window.generate_message_id = function (type) {\n        var message_id = new Date().getTime() + \"_\" + Math.floor((Math.random() * 10000000000) + 1000);\n\n        if (type &amp;&amp; type === \"image\") {\n            message_id += \"_v1.jpg\";\n        }\n\n        return message_id;\n    };<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Structure of the POST request<\/h2>\n\n\n\n<p>The following entries are slightly abbreviated<\/p>\n\n\n\n<p>Cookies<\/p>\n\n\n\n<p>There are a bunch of tracking cookies, the session cookie is the one we are interested in.  The Rv_session_key is what will allow us to actually send messages.  As a side note, it appears that every time we send a message, there is analytics that is also sent, saying who the message was sent to, and when.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">session={\"gcp1-prod\":{\"user_id\":\"MyVoxerUser_ID\",\"Rv_session_key\":\"db0bc8a069148140151a38bab2098a01\"}}<\/pre>\n\n\n\n<p>Body<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">{\"message_id\":\"1681191108600_7318671093\",\"create_time\":1681191108,\"model\":\"User_Agent\",\"content_type\":\"text\",\"from\":\"MyVoxerUser_ID\",\"subject\":\"Walkie\",\"body\":\"This is the text of the message\",\"thread_id\":\"This.is.the.thread_id\"}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Using JavaScript \/ fetch<\/h2>\n\n\n\n<p>After some trial an error, the following solution finally worked.  You can copy the following code, and run with &#8220;node file.js&#8221;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\/\/ Change variables as needed\nlet body = \"Hello World!\"\n\/\/ let body = process.argv.slice(2) \/\/ You can use this if you want to pass in the message as an argumant. i.e. node voxer.js \"Voxer Message\"\nconst threadID = 'ThreadID'\nconst fromID = 'UserID'\nlet cookie = `session={\"gcp1-prod\":{\"user_id\":\"${fromID}\",\"Rv_session_key\":\"RVSESSIONID\"}}`\nlet time = new Date().getTime() \/ 1000\nlet messageID = new Date().getTime() + '_' + Math.floor(Math.random() * 10000000000 + 1000)\n\n\/\/ Send message.\nfunction sendMessage () {\n  fetch(`https:\/\/gcp1-prod-nr60.voxer.com\/2\/cs\/post_message?now=${time}`, {\n    credentials: 'include',\n    credentials: 'same-origin',\n    headers: {\n      'User-Agent': 'UserAgent',\n      Accept: '*\/*',\n      'Accept-Language': 'en-US,en;q=0.5',\n      'Content-Type': 'text\/plain',\n      'Sec-Fetch-Dest': 'empty',\n      'Sec-Fetch-Mode': 'cors',\n      'Sec-Fetch-Site': 'same-site',\n      'sec-ch-ua-platform': '\"Windows\"',\n      'sec-ch-ua': '\"Opera\";v=\"97\", \"Chromium\";v=\"97\", \"Not=A?Brand\";v=\"24\"',\n      'sec-ch-ua-mobile': '?0',\n      Cookie: cookie\n    },\n    referrer: 'https:\/\/web.voxer.com\/',\n    body: `{\\\"message_id\\\":\\\"${messageID}\\\",\\\"create_time\\\":${time},\\\"model\\\":\\\"\\\",\\\"content_type\\\":\\\"text\\\",\\\"from\\\":\\\"${fromID}\\\",\\\"subject\\\":\\\"CHANGING\\\",\\\"body\\\":\\\"${body}\\\\n\\\",\\\"thread_id\\\":\\\"${threadID}\\\"}\\r\\n`,\n    method: 'POST',\n    mode: 'cors'\n  })}\n\n sendMessage()\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><\/h2>\n\n\n\n<p>You can find the thread_id, user_id, session cookie by toggling the developer console, logging into Voxer, and send a message.  <\/p>\n","protected":false},"excerpt":{"rendered":"<p>The following are various notes and findings on trying to create a &#8220;Bot&#8221; for Voxer. Voxer doesn&#8217;t really have any options for web hooks, and the SDK is still in beta. We&#8217;ll be exploring sending messages to a channel, how &hellip; <a href=\"https:\/\/www.incredigeek.com\/home\/voxer-bot-attempts-1-of-3\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[809],"tags":[1286,244,1492,1198,225,1419,1437,1463,639,1471,1420,1491],"class_list":["post-5059","post","type-post","status-publish","format-standard","hentry","category-random","tag-api","tag-automation","tag-bot","tag-chat","tag-curl","tag-fetch","tag-javascript","tag-js","tag-message","tag-node","tag-post","tag-voxer"],"_links":{"self":[{"href":"https:\/\/www.incredigeek.com\/home\/wp-json\/wp\/v2\/posts\/5059","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.incredigeek.com\/home\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.incredigeek.com\/home\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.incredigeek.com\/home\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.incredigeek.com\/home\/wp-json\/wp\/v2\/comments?post=5059"}],"version-history":[{"count":5,"href":"https:\/\/www.incredigeek.com\/home\/wp-json\/wp\/v2\/posts\/5059\/revisions"}],"predecessor-version":[{"id":5227,"href":"https:\/\/www.incredigeek.com\/home\/wp-json\/wp\/v2\/posts\/5059\/revisions\/5227"}],"wp:attachment":[{"href":"https:\/\/www.incredigeek.com\/home\/wp-json\/wp\/v2\/media?parent=5059"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.incredigeek.com\/home\/wp-json\/wp\/v2\/categories?post=5059"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.incredigeek.com\/home\/wp-json\/wp\/v2\/tags?post=5059"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}