|
@@ -0,0 +1,183 @@
|
|
|
|
|
+// Zoho Cliq API Module
|
|
|
|
|
+// EU data center: https://cliq.zoho.eu
|
|
|
|
|
+// API: https://www.zoho.com/cliq/help/restapi/v2/
|
|
|
|
|
+
|
|
|
|
|
+var API_BASE = 'https://cliq.zoho.eu';
|
|
|
|
|
+
|
|
|
|
|
+function makeRequest(token, method, path, jsonBody, queryParams) {
|
|
|
|
|
+ var url = API_BASE + path;
|
|
|
|
|
+
|
|
|
|
|
+ if (queryParams) {
|
|
|
|
|
+ var qs = [];
|
|
|
|
|
+ for (var key in queryParams) {
|
|
|
|
|
+ if (queryParams.hasOwnProperty(key) && queryParams[key] !== undefined) {
|
|
|
|
|
+ qs.push(encodeURIComponent(key) + '=' + encodeURIComponent(queryParams[key]));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (qs.length > 0) {
|
|
|
|
|
+ url += '?' + qs.join('&');
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ var headers = {
|
|
|
|
|
+ 'Authorization': 'Zoho-oauthtoken ' + token
|
|
|
|
|
+ };
|
|
|
|
|
+ var body = null;
|
|
|
|
|
+
|
|
|
|
|
+ if (jsonBody) {
|
|
|
|
|
+ body = JSON.stringify(jsonBody);
|
|
|
|
|
+ headers['Content-Type'] = 'application/json;charset=UTF-8';
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ var resp = shadowman.http.request(url, {
|
|
|
|
|
+ method: method,
|
|
|
|
|
+ body: body,
|
|
|
|
|
+ headers: headers
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ if (resp.status === 401) {
|
|
|
|
|
+ return { _tokenExpired: true };
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (resp.status >= 400) {
|
|
|
|
|
+ var raw = resp.body;
|
|
|
|
|
+ var msg;
|
|
|
|
|
+ if (typeof raw === 'string') {
|
|
|
|
|
+ try {
|
|
|
|
|
+ var p = JSON.parse(raw);
|
|
|
|
|
+ msg = p.error && p.error.message ? p.error.message : raw;
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ msg = raw;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if (raw && typeof raw === 'object') {
|
|
|
|
|
+ msg = (raw.error && raw.error.message) || raw.message || raw.description || JSON.stringify(raw);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ msg = String(raw);
|
|
|
|
|
+ }
|
|
|
|
|
+ return { error: 'Zoho Cliq API error (' + resp.status + '): ' + msg };
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (resp.body && typeof resp.body === 'object') {
|
|
|
|
|
+ return resp.body;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!resp.body || (typeof resp.body === 'string' && resp.body.trim() === '')) {
|
|
|
|
|
+ return { success: true };
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ return JSON.parse(resp.body);
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ return { error: 'Invalid JSON response: ' + resp.body };
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function apiCall(token, method, path, jsonBody, queryParams) {
|
|
|
|
|
+ var result = makeRequest(token, method, path, jsonBody, queryParams);
|
|
|
|
|
+ if (result && result._tokenExpired) {
|
|
|
|
|
+ var auth = require('./auth');
|
|
|
|
|
+ var newToken = auth.getValidToken();
|
|
|
|
|
+ if (!newToken) {
|
|
|
|
|
+ return { error: 'Authentication expired and refresh failed. Re-run setup_auth.' };
|
|
|
|
|
+ }
|
|
|
|
|
+ return makeRequest(newToken, method, path, jsonBody, queryParams);
|
|
|
|
|
+ }
|
|
|
|
|
+ return result;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// --- List chats (channels + direct chats) ---
|
|
|
|
|
+// GET /api/v2/chats
|
|
|
|
|
+
|
|
|
|
|
+function listChats(token) {
|
|
|
|
|
+ return apiCall(token, 'GET', '/api/v2/chats');
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// --- List channels ---
|
|
|
|
|
+// GET /api/v2/channels
|
|
|
|
|
+
|
|
|
|
|
+function listChannels(token) {
|
|
|
|
|
+ return apiCall(token, 'GET', '/api/v2/channels');
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// --- Get messages from a chat ---
|
|
|
|
|
+// GET /api/v2/chats/{chat_id}/messages
|
|
|
|
|
+
|
|
|
|
|
+function getMessages(token, chatId) {
|
|
|
|
|
+ return apiCall(token, 'GET',
|
|
|
|
|
+ '/api/v2/chats/{CHATID}/messages'
|
|
|
|
|
+ .replace('{CHATID}', chatId));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// --- Post message to a chat ---
|
|
|
|
|
+// POST /api/v2/chats/{chat_id}/message (singular!)
|
|
|
|
|
+
|
|
|
|
|
+function sendMessage(token, chatId, message) {
|
|
|
|
|
+ var url = API_BASE + '/api/v2/chats/' + chatId + '/message';
|
|
|
|
|
+ var body = JSON.stringify({ text: message });
|
|
|
|
|
+ var headers = {
|
|
|
|
|
+ 'Authorization': 'Zoho-oauthtoken ' + token,
|
|
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
|
|
+ };
|
|
|
|
|
+ return makeRawRequest(token, 'POST', url, body, headers);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// --- Post message to a channel ---
|
|
|
|
|
+// POST /api/v2/channelsbyname/{channel_unique_name}/message
|
|
|
|
|
+
|
|
|
|
|
+function postToChannel(token, channelName, message) {
|
|
|
|
|
+ var url = API_BASE + '/api/v2/channelsbyname/' + channelName + '/message';
|
|
|
|
|
+ var body = JSON.stringify({ text: message });
|
|
|
|
|
+ var headers = {
|
|
|
|
|
+ 'Authorization': 'Zoho-oauthtoken ' + token,
|
|
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
|
|
+ };
|
|
|
|
|
+ return makeRawRequest(token, 'POST', url, body, headers);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function makeRawRequest(token, method, url, body, headers) {
|
|
|
|
|
+ var resp = shadowman.http.request(url, {
|
|
|
|
|
+ method: method,
|
|
|
|
|
+ body: body,
|
|
|
|
|
+ headers: headers
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ if (resp.status >= 400) {
|
|
|
|
|
+ var raw = resp.body;
|
|
|
|
|
+ var msg;
|
|
|
|
|
+ if (typeof raw === 'string') {
|
|
|
|
|
+ try {
|
|
|
|
|
+ var p = JSON.parse(raw);
|
|
|
|
|
+ msg = p.error && p.error.message ? p.error.message : raw;
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ msg = raw;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if (raw && typeof raw === 'object') {
|
|
|
|
|
+ msg = (raw.error && raw.error.message) || raw.message || raw.description || JSON.stringify(raw);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ msg = String(raw);
|
|
|
|
|
+ }
|
|
|
|
|
+ return { error: 'Zoho Cliq API error (' + resp.status + '): ' + msg };
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (resp.body && typeof resp.body === 'object') {
|
|
|
|
|
+ return resp.body;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!resp.body || (typeof resp.body === 'string' && resp.body.trim() === '')) {
|
|
|
|
|
+ return { success: true };
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ return JSON.parse(resp.body);
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ return { error: 'Invalid JSON response: ' + resp.body };
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+module.exports = {
|
|
|
|
|
+ listChats: listChats,
|
|
|
|
|
+ listChannels: listChannels,
|
|
|
|
|
+ getMessages: getMessages,
|
|
|
|
|
+ sendMessage: sendMessage,
|
|
|
|
|
+ postToChannel: postToChannel
|
|
|
|
|
+};
|