cliq.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. // Zoho Cliq API Module
  2. // EU data center: https://cliq.zoho.eu
  3. // API: https://www.zoho.com/cliq/help/restapi/v2/
  4. var API_BASE = 'https://cliq.zoho.eu';
  5. function makeRequest(token, method, path, jsonBody, queryParams) {
  6. var url = API_BASE + path;
  7. if (queryParams) {
  8. var qs = [];
  9. for (var key in queryParams) {
  10. if (queryParams.hasOwnProperty(key) && queryParams[key] !== undefined) {
  11. qs.push(encodeURIComponent(key) + '=' + encodeURIComponent(queryParams[key]));
  12. }
  13. }
  14. if (qs.length > 0) {
  15. url += '?' + qs.join('&');
  16. }
  17. }
  18. var headers = {
  19. 'Authorization': 'Zoho-oauthtoken ' + token
  20. };
  21. var body = null;
  22. if (jsonBody) {
  23. body = JSON.stringify(jsonBody);
  24. headers['Content-Type'] = 'application/json;charset=UTF-8';
  25. }
  26. var resp = shadowman.http.request(url, {
  27. method: method,
  28. body: body,
  29. headers: headers
  30. });
  31. if (resp.status === 401) {
  32. return { _tokenExpired: true };
  33. }
  34. if (resp.status >= 400) {
  35. var raw = resp.body;
  36. var msg;
  37. if (typeof raw === 'string') {
  38. try {
  39. var p = JSON.parse(raw);
  40. msg = p.error && p.error.message ? p.error.message : raw;
  41. } catch (e) {
  42. msg = raw;
  43. }
  44. } else if (raw && typeof raw === 'object') {
  45. msg = (raw.error && raw.error.message) || raw.message || raw.description || JSON.stringify(raw);
  46. } else {
  47. msg = String(raw);
  48. }
  49. return { error: 'Zoho Cliq API error (' + resp.status + '): ' + msg };
  50. }
  51. if (resp.body && typeof resp.body === 'object') {
  52. return resp.body;
  53. }
  54. if (!resp.body || (typeof resp.body === 'string' && resp.body.trim() === '')) {
  55. return { success: true };
  56. }
  57. try {
  58. return JSON.parse(resp.body);
  59. } catch (e) {
  60. return { error: 'Invalid JSON response: ' + resp.body };
  61. }
  62. }
  63. function apiCall(token, method, path, jsonBody, queryParams) {
  64. var result = makeRequest(token, method, path, jsonBody, queryParams);
  65. if (result && result._tokenExpired) {
  66. var auth = require('./auth');
  67. var newToken = auth.getValidToken();
  68. if (!newToken) {
  69. return { error: 'Authentication expired and refresh failed. Re-run setup_auth.' };
  70. }
  71. return makeRequest(newToken, method, path, jsonBody, queryParams);
  72. }
  73. return result;
  74. }
  75. // --- List chats (channels + direct chats) ---
  76. // GET /api/v2/chats
  77. function listChats(token) {
  78. return apiCall(token, 'GET', '/api/v2/chats');
  79. }
  80. // --- List channels ---
  81. // GET /api/v2/channels
  82. function listChannels(token) {
  83. return apiCall(token, 'GET', '/api/v2/channels');
  84. }
  85. // --- Get messages from a chat ---
  86. // GET /api/v2/chats/{chat_id}/messages
  87. function getMessages(token, chatId) {
  88. return apiCall(token, 'GET',
  89. '/api/v2/chats/{CHATID}/messages'
  90. .replace('{CHATID}', chatId));
  91. }
  92. // --- Post message to a chat ---
  93. // POST /api/v2/chats/{chat_id}/message (singular!)
  94. function sendMessage(token, chatId, message) {
  95. var url = API_BASE + '/api/v2/chats/' + chatId + '/message';
  96. var body = JSON.stringify({ text: message });
  97. var headers = {
  98. 'Authorization': 'Zoho-oauthtoken ' + token,
  99. 'Content-Type': 'application/json'
  100. };
  101. return makeRawRequest(token, 'POST', url, body, headers);
  102. }
  103. // --- Post message to a channel ---
  104. // POST /api/v2/channelsbyname/{channel_unique_name}/message
  105. function postToChannel(token, channelName, message) {
  106. var url = API_BASE + '/api/v2/channelsbyname/' + channelName + '/message';
  107. var body = JSON.stringify({ text: message });
  108. var headers = {
  109. 'Authorization': 'Zoho-oauthtoken ' + token,
  110. 'Content-Type': 'application/json'
  111. };
  112. return makeRawRequest(token, 'POST', url, body, headers);
  113. }
  114. function makeRawRequest(token, method, url, body, headers) {
  115. var resp = shadowman.http.request(url, {
  116. method: method,
  117. body: body,
  118. headers: headers
  119. });
  120. if (resp.status >= 400) {
  121. var raw = resp.body;
  122. var msg;
  123. if (typeof raw === 'string') {
  124. try {
  125. var p = JSON.parse(raw);
  126. msg = p.error && p.error.message ? p.error.message : raw;
  127. } catch (e) {
  128. msg = raw;
  129. }
  130. } else if (raw && typeof raw === 'object') {
  131. msg = (raw.error && raw.error.message) || raw.message || raw.description || JSON.stringify(raw);
  132. } else {
  133. msg = String(raw);
  134. }
  135. return { error: 'Zoho Cliq API error (' + resp.status + '): ' + msg };
  136. }
  137. if (resp.body && typeof resp.body === 'object') {
  138. return resp.body;
  139. }
  140. if (!resp.body || (typeof resp.body === 'string' && resp.body.trim() === '')) {
  141. return { success: true };
  142. }
  143. try {
  144. return JSON.parse(resp.body);
  145. } catch (e) {
  146. return { error: 'Invalid JSON response: ' + resp.body };
  147. }
  148. }
  149. module.exports = {
  150. listChats: listChats,
  151. listChannels: listChannels,
  152. getMessages: getMessages,
  153. sendMessage: sendMessage,
  154. postToChannel: postToChannel
  155. };