├── README.md ├── LICENSE ├── index.html └── frontend.js /README.md: -------------------------------------------------------------------------------- 1 | ## API Channel Public API demo 2 | 3 | This repo is a POC implementation using Public API of Chatwoot's API Channels. 4 | 5 | ### Steps 6 | 7 | 1) Create an API Channel in chatwoot and obtain the channel identifier 8 | ``` 9 | # replace api_inbox_id with your inbox id 10 | Inbox.find(api_inbox_id).channel.identifier 11 | ``` 12 | 2) Edit `frontend.js` and update `chatwoot.inboxIdentifier` with the value of channel identifier. 13 | 3) Run and local server and try interacting with the interface 14 | ``` 15 | python3 -m http.server 16 | ``` 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Chatwoot 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |', { text: 'Sorry, but your browser doesn\'t ' 22 | + 'support WebSockets.'} )); 23 | input.hide(); 24 | $('span').hide(); 25 | return; 26 | } 27 | 28 | // open connection 29 | var connection = new WebSocket('ws://localhost:3000/cable'); 30 | 31 | connection.onopen = function () { 32 | // check whether we have a pubsub token and contact identifier or else set one 33 | setUpContact(); 34 | setUpConversation(); 35 | 36 | // first we want users to subscribe to the chatwoot webhooks 37 | connection.send(JSON.stringify({command:"subscribe", identifier: "{\"channel\":\"RoomChannel\",\"pubsub_token\":\""+chatwoot.contactPubsubToken+"\"}" })); 38 | input.removeAttr('disabled'); 39 | status.text('Send Message:'); 40 | }; 41 | 42 | connection.onerror = function (error) { 43 | // just in there were some problems with connection... 44 | content.html($('
', { text: 'Sorry, but there\'s some problem with your ' 45 | + 'connection or the server is down.' } )); 46 | }; 47 | 48 | // most important part - incoming messages 49 | connection.onmessage = function (message) { 50 | // try to parse JSON message. Because we know that the server always returns 51 | // JSON this should work without any problem but we should make sure that 52 | // the massage is not chunked or otherwise damaged. 53 | try { 54 | var json = JSON.parse(message.data); 55 | } catch (e) { 56 | console.log('This doesn\'t look like a valid JSON: ', message.data); 57 | return; 58 | } 59 | 60 | if (json.type === 'welcome') { 61 | // lets ignore the welcome 62 | } else if (json.type === 'ping') { 63 | // lets ignore the pings 64 | } else if (json.type === 'confirm_subscription') { 65 | // lets ignore the confirmation 66 | }else if (json.message.event === 'message.created') { 67 | console.log('here comes message', json); 68 | if(json.message.data.message_type === 1) 69 | { 70 | addMessage(json.message.data.sender.name, json.message.data.content); 71 | } 72 | } else { 73 | console.log('Hmm..., I\'ve never seen JSON like this: ', json); 74 | } 75 | }; 76 | 77 | /** 78 | * Send mesage when user presses Enter key 79 | */ 80 | input.keydown(function(e) { 81 | if (e.keyCode === 13) { 82 | var msg = $(this).val(); 83 | if (!msg) { 84 | return; 85 | } 86 | // send the message to chatwoot 87 | //connection.send(msg); 88 | sendMessage(msg); 89 | addMessage("me", msg) 90 | $(this).val(''); 91 | } 92 | }); 93 | 94 | /** 95 | * This method is optional. If the server wasn't able to respond to the 96 | * in 3 seconds then show some error message to notify the user that 97 | * something is wrong. 98 | */ 99 | setInterval(function() { 100 | if (connection.readyState !== 1) { 101 | status.text('Error'); 102 | input.attr('disabled', 'disabled').val('Unable to communicate ' 103 | + 'with the WebSocket server.'); 104 | } 105 | }, 3000); 106 | 107 | /** 108 | * Add message to the chat window 109 | */ 110 | function addMessage(author, message) { 111 | content.append('
' + author + ' @ ' + ':' + message + '
'); 112 | content.scrollTop(1000000); 113 | } 114 | 115 | function setUpContact() { 116 | if(getCookie('contactIdentifier')){ 117 | chatwoot.contactIdentifier = getCookie('contactIdentifier'); 118 | chatwoot.contactPubsubToken = getCookie('contactPubsubToken') 119 | }else{ 120 | xhttp.open("POST", chatwoot.chatwootAPIUrl + "inboxes/"+chatwoot.inboxIdentifier+"/contacts"); 121 | xhttp.send(); 122 | var contactPubsubToken = JSON.parse(xhttp.responseText).pubsub_token; 123 | var contactIdentifier = JSON.parse(xhttp.responseText).source_id; 124 | setCookie('contactIdentifier',contactIdentifier,30); 125 | setCookie('contactPubsubToken',contactPubsubToken,30); 126 | } 127 | } 128 | 129 | function setUpConversation() { 130 | if(getCookie('contactConverstion')){ 131 | chatwoot.contactConverstion = getCookie('contactConverstion'); 132 | }else{ 133 | xhttp.open("POST", chatwoot.chatwootAPIUrl + "inboxes/"+chatwoot.inboxIdentifier+"/contacts/"+chatwoot.contactIdentifier+"/conversations", false); 134 | xhttp.send(); 135 | var contactConverstion = JSON.parse(xhttp.responseText).id; 136 | setCookie('contactConverstion',contactConverstion,30); 137 | } 138 | } 139 | 140 | function sendMessage(msg){ 141 | xhttp.open("POST", chatwoot.chatwootAPIUrl + "inboxes/"+chatwoot.inboxIdentifier+"/contacts/"+chatwoot.contactIdentifier+"/conversations/"+chatwoot.contactConverstion+"/messages", false); 142 | xhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); 143 | xhttp.send(JSON.stringify({content: msg})); 144 | } 145 | 146 | function setCookie(name,value,days) { 147 | var expires = ""; 148 | if (days) { 149 | var date = new Date(); 150 | date.setTime(date.getTime() + (days*24*60*60*1000)); 151 | expires = "; expires=" + date.toUTCString(); 152 | } 153 | document.cookie = name + "=" + (value || "") + expires + "; path=/"; 154 | } 155 | function getCookie(name) { 156 | var nameEQ = name + "="; 157 | var ca = document.cookie.split(';'); 158 | for(var i=0;i < ca.length;i++) { 159 | var c = ca[i]; 160 | while (c.charAt(0)==' ') c = c.substring(1,c.length); 161 | if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length); 162 | } 163 | return null; 164 | } 165 | function eraseCookie(name) { 166 | document.cookie = name +'=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;'; 167 | } 168 | }); --------------------------------------------------------------------------------