diff --git a/README.md b/README.md index 7870fa5..1aca63c 100644 --- a/README.md +++ b/README.md @@ -210,6 +210,43 @@ Function URL (factsAboutGoogle): https://us-central1-myprojectname-ab123.cloudfu 22. Finally We Are Done ! +#### AWS Lambda Deployment +The fulfillment code can also be deployed in AWS as a lambda function as an alternative to using Firebase. + +1. Navigate to the AWS Lambda console. + + +2. Create a new function with the following settings. + + Author From Scratch + + Runtime: Node.js 12.x + + Permissions: Create a new role with basic Lambda Permissions + + +3. Add the following Environment Variables +``` +OAUTH_SERVICE_NAME => Name of the Custom OAuth service created in Rocket Chat OAuth Settings +SERVER_URL => Rocket Chat server url (https://YOUR.SERVER.chat) +``` + +4. Add an API Gateway trigger with the following settings. + + Create an API + + API Type: HTTP API + + Security: Open + +5. Copy the following value somewhere. + + Click on API Gateway > Details > API endpoint + +6. Navigate to Dialogflow > Fulfillment section: https://dialogflow.cloud.google.com/#/agent/project_id/fulfillment + + Paste the API endpoint in the Webhook URL field. + +7. To upload the backend code in Lambda function + + Navigate to `./functions` directory in the project repository + + Select all files and compress into a zip file. + + In the **Functions Code** section of AWS Lambda Function + + Actions > Upload a .zip file + + Select the compressed zip file + + Click **Save**. + --- ## Running this Action @@ -218,7 +255,21 @@ Function URL (factsAboutGoogle): https://us-central1-myprojectname-ab123.cloudfu --- -## Development +## Development + +#### Local Development Setup +The project can be run on local development for debugging. The steps are listed below. +1. Create an environment file inside the functions folder. + + `./functions/.env` +2. Add the following variables +``` +SERVER_URL= +OAUTH_SERVICE_NAME= +``` +3. Start the server locally by running `npm run local` +4. Create a tunnel using ngrok `ngrok http 3000` +5. Navigate to Dialogflow > Fulfillment section: https://dialogflow.cloud.google.com/#/agent/project_id/fulfillment + + Paste the URL generated by ngrok in the Webhook URL field. #### Files 1. `./functions/index.js` diff --git a/agent.zip b/agent.zip index df7d179..e792e53 100644 Binary files a/agent.zip and b/agent.zip differ diff --git a/functions/apiEndpoints.js b/functions/apiEndpoints.js index d476e51..a6334b1 100644 --- a/functions/apiEndpoints.js +++ b/functions/apiEndpoints.js @@ -15,6 +15,9 @@ module.exports = { deletechannelurl: `${ SERVER_URL }/api/v1/channels.delete`, postmessageurl: `${ SERVER_URL }/api/v1/chat.postMessage`, channelmessageurl: `${ SERVER_URL }/api/v1/channels.messages?roomName=`, + immessageurl: `${ SERVER_URL }/api/v1/im.messages`, + imcountersurl: `${ SERVER_URL }/api/v1/im.counters`, + groupmessageurlname: `${ SERVER_URL }/api/v1/groups.messages?roomName=`, channelmentionsurl: `${ SERVER_URL }/api/v1/channels.getAllUserMentionsByChannel?roomId=`, channelinfourl: `${ SERVER_URL }/api/v1/channels.info?roomName=`, userinfourl: `${ SERVER_URL }/api/v1/users.info?username=`, @@ -23,6 +26,7 @@ module.exports = { addownerurl: `${ SERVER_URL }/api/v1/channels.addOwner`, archivechannelurl: `${ SERVER_URL }/api/v1/channels.archive`, counterurl: `${ SERVER_URL }/api/v1/channels.counters?roomName=`, + channelcountersidurl: `${ SERVER_URL }/api/v1/channels.counters?roomId=`, inviteuserurl: `${ SERVER_URL }/api/v1/channels.invite`, leavechannelurl: `${ SERVER_URL }/api/v1/channels.leave`, kickuserurl: `${ SERVER_URL }/api/v1/channels.kick`, @@ -56,5 +60,15 @@ module.exports = { groupannouncementurl: `${ SERVER_URL }/api/v1/groups.setAnnouncement`, unarchivegroupurl: `${ SERVER_URL }/api/v1/groups.unarchive`, groupmessageurl: `${ SERVER_URL }/api/v1/groups.messages?roomId=`, + groupmessagenameurl: `${ SERVER_URL }/api/v1/groups.messages?roomName=`, groupcounterurl: `${ SERVER_URL }/api/v1/groups.counters?roomId=`, + groupcounternameurl: `${ SERVER_URL }/api/v1/groups.counters?roomName=`, + channellisturl: `${ SERVER_URL }/api/v1/channels.list.joined`, + grouplisturl: `${ SERVER_URL }/api/v1/groups.list`, + getsubscriptionsurl: `${ SERVER_URL }/api/v1/subscriptions.get`, + getmentionedmessagesurl: `${ SERVER_URL }/api/v1/chat.getMentionedMessages`, + imlisturl: `${ SERVER_URL }/api/v1/im.list`, + getrolesfromchannelurl: `${ SERVER_URL }/api/v1/channels.roles`, + getrolesfromgroupurl: `${ SERVER_URL }/api/v1/groups.roles`, + setstatusurl: `${ SERVER_URL }/api/v1/users.setStatus`, }; \ No newline at end of file diff --git a/functions/config.js b/functions/config.js index 90fbbfc..12bb2dd 100644 --- a/functions/config.js +++ b/functions/config.js @@ -1,8 +1,25 @@ // Environment Variables -const functions = require('firebase-functions'); - -module.exports = { - SERVER_URL : functions.config().envariables.server_url, - CLIENT_ID : functions.config().envariables.clientid, - OAUTH_SERVICE_NAME : functions.config().envariables.oauth_service_name -}; +if (process.env.DEVELOPMENT) { + // if code is running in local + require('dotenv').config(); + module.exports = { + SERVER_URL: process.env.SERVER_URL, + CLIENT_ID: process.env.CLIENT_ID, + OAUTH_SERVICE_NAME: process.env.OAUTH_SERVICE_NAME + } +} else if(Boolean(process.env['AWS_LAMBDA_FUNCTION_NAME'])) { + // if code is deployed in aws lambda function + module.exports = { + SERVER_URL: process.env.SERVER_URL, + CLIENT_ID: process.env.CLIENT_ID, + OAUTH_SERVICE_NAME: process.env.OAUTH_SERVICE_NAME + } +} else { + // if code is deployed in firebase function + const functions = require('firebase-functions'); + module.exports = { + SERVER_URL : functions.config().envariables.server_url, + CLIENT_ID : functions.config().envariables.clientid, + OAUTH_SERVICE_NAME : functions.config().envariables.oauth_service_name + }; +} diff --git a/functions/helperFunctions.js b/functions/helperFunctions.js index 7c9440c..775de30 100644 --- a/functions/helperFunctions.js +++ b/functions/helperFunctions.js @@ -4,9 +4,11 @@ const envVariables = require('./config'); const removeWhitespace = require('remove-whitespace'); const emojiTranslate = require('moji-translate'); +const stringSimilar = require('string-similarity') const i18n = require('i18n'); -var translate = require("@vitalets/google-translate-api") +// this import throws an error in lambda environment, a different translate method required +// var translate = require("@vitalets/google-translate-api") // Server Credentials. Follow readme to set them up. const { @@ -22,7 +24,6 @@ const login = async (accessToken) => }) .then((res) => res.data) .then((res) => { - console.log(res); const headers = { 'X-Auth-Token': res.data.authToken, 'X-User-Id': res.data.userId, @@ -33,6 +34,52 @@ const login = async (accessToken) => console.log(err); }); +const userDetails = async (accessToken) => { + try{ + const response = await axios + .post(apiEndpoints.loginUrl, { + serviceName: OAUTH_SERVICE_NAME, + accessToken, + expiresIn: 200, + }) + .then((res) => res.data.data.me) + return response; + }catch(err) { + console.log(err); + } +} + +// this helper function will return the user headers along with some user details +const getCurrentUserDetails = async (accessToken) => { + try{ + const response = await axios + .post(apiEndpoints.loginUrl, { + serviceName: OAUTH_SERVICE_NAME, + accessToken, + expiresIn: 200, + }) + .then((res) => res.data.data) + + const headers = { + 'X-Auth-Token': response.authToken, + 'X-User-Id': response.userId, + }; + + const userDetails = { + id: response.me._id, + name: response.me.name, + username: response.me.username, + statusText: response.me.statusText, + avatarUrl: response.me.avatarUrl, + } + + return {headers, userDetails}; + }catch(err) { + console.log(err); + throw err; + } +} + const createChannel = async (channelName, headers) => await axios .post( @@ -63,38 +110,39 @@ const createChannel = async (channelName, headers) => } }); -const deleteChannel = async (channelName, headers) => - await axios - .post( - apiEndpoints.deletechannelurl, { - roomName: channelName, - }, { - headers - } - ) - .then((res) => res.data) - .then((res) => { - if (res.success === true) { - return i18n.__('DELETE_CHANNEL.SUCCESS', channelName); +const deleteChannel = async (channelDetails, headers) => { + try{ + const response = await axios + .post( + channelDetails.type === 'c' ? apiEndpoints.deletechannelurl : apiEndpoints.deletegroupurl, { + roomName: channelDetails.name, + }, { + headers + } + ) + .then((res) => res.data) + + if (response.success === true) { + return i18n.__('DELETE_CHANNEL.SUCCESS', channelDetails.name); } else { - return i18n.__('DELETE_CHANNEL.ERROR', channelName); + return i18n.__('DELETE_CHANNEL.ERROR', channelDetails.name); } - }) - .catch((err) => { + }catch(err) { console.log(err.message); if (err.response.data.errorType === 'error-room-not-found') { - return i18n.__('DELETE_CHANNEL.ERROR_NOT_FOUND', channelName); + return i18n.__('DELETE_CHANNEL.ERROR_NOT_FOUND', channelDetails.name); } else { - return i18n.__('DELETE_CHANNEL.ERROR', channelName); + return i18n.__('DELETE_CHANNEL.ERROR', channelDetails.name); } - }); + }; +} const postMessage = async (channelName, message, headers) => await axios .post( apiEndpoints.postmessageurl, { channel: `#${ channelName }`, - text: message, + text: message[0].toUpperCase() + message.slice(1), //make the first letter upper case }, { headers } @@ -156,28 +204,29 @@ const getRoomId = async (channelName, headers) => console.log(err.message); }); -const makeModerator = async (userName, channelName, userid, roomid, headers) => - await axios - .post( - apiEndpoints.makemoderatorurl, { - userId: userid, - roomId: roomid, - }, { - headers - } - ) - .then((res) => res.data) - .then((res) => { - if (res.success === true) { - return i18n.__('MAKE_MODERATOR.SUCCESS', userName, channelName); +const makeModerator = async (userDetails, channelDetails, headers) => { + try{ + const response = await axios + .post( + channelDetails.type === 'c' ? apiEndpoints.makemoderatorurl : apiEndpoints.addgroupmoderatorurl, { + userId: userDetails.id, + roomId: channelDetails.id, + }, { + headers + } + ) + .then((res) => res.data) + + if (response.success === true) { + return i18n.__('MAKE_MODERATOR.SUCCESS', userDetails.name, channelDetails.name); } else { return i18n.__('MAKE_MODERATOR.ERROR'); } - }) - .catch((err) => { + }catch(err) { console.log(err.message); - return i18n.__('MAKE_MODERATOR.ERROR_NOT_FOUND', channelName); - }); + return i18n.__('MAKE_MODERATOR.ERROR_NOT_FOUND', channelDetails.name); + }; +} const addAll = async (channelName, roomid, headers) => await axios @@ -201,50 +250,52 @@ const addAll = async (channelName, roomid, headers) => return i18n.__('ADD_ALL_TO_CHANNEL.ERROR_NOT_FOUND', channelName); }); -const addOwner = async (userName, channelName, userid, roomid, headers) => - await axios - .post( - apiEndpoints.addownerurl, { - userId: userid, - roomId: roomid, - }, { - headers - } - ) - .then((res) => res.data) - .then((res) => { - if (res.success === true) { - return i18n.__('ADD_OWNER.SUCCESS', userName, channelName); +const addOwner = async (userDetails, channelDetails, headers) => { + try{ + const response = await axios + .post( + channelDetails.type === 'c' ? apiEndpoints.addownerurl : apiEndpoints.addgroupownerurl, { + userId: userDetails.id, + roomId: channelDetails.id, + }, { + headers + } + ) + .then((res) => res.data) + + if (response.success === true) { + return i18n.__('ADD_OWNER.SUCCESS', userDetails.name, channelDetails.name); } else { return i18n.__('ADD_OWNER.ERROR'); } - }) - .catch((err) => { + }catch(err) { console.log(err.message); - return i18n.__('ADD_OWNER.ERROR_NOT_FOUND', channelName); - }); + return i18n.__('ADD_OWNER.ERROR_NOT_FOUND', channelDetails.name); + }; +} -const archiveChannel = async (channelName, roomid, headers) => - await axios - .post( - apiEndpoints.archivechannelurl, { - roomId: roomid, - }, { - headers - } - ) - .then((res) => res.data) - .then((res) => { - if (res.success === true) { - return i18n.__('ARCHIVE_CHANNEL.SUCCESS', channelName); +const archiveChannel = async (channelDetails, headers) => { + try{ + const response = await axios + .post( + channelDetails.type === 'c' ? apiEndpoints.archivechannelurl : apiEndpoints.archivegroupurl, { + roomId: channelDetails.id, + }, { + headers + } + ) + .then((res) => res.data) + + if (response.success === true) { + return i18n.__('ARCHIVE_CHANNEL.SUCCESS', channelDetails.name); } else { return i18n.__('ARCHIVE_CHANNEL.ERROR'); } - }) - .catch((err) => { + }catch(err) { console.log(err.message); - return i18n.__('ARCHIVE_CHANNEL.ERROR_NOT_FOUND', channelName); - }); + return i18n.__('ARCHIVE_CHANNEL.ERROR_NOT_FOUND', channelDetails.name); + }; +} function replaceWhitespacesFunc(str) { return removeWhitespace(str); @@ -259,9 +310,9 @@ function emojiTranslateFunc(str) { return emojiTranslate.translate(str, onlyEmoji); } -const getUnreadCounter = async (channelName, headers) => +const getUnreadCounter = async (channelName, type, headers) => await axios - .get(`${ apiEndpoints.counterurl }${ channelName }`, { + .get(`${ type === 'c' ? apiEndpoints.counterurl : apiEndpoints.groupcounternameurl }${ channelName }`, { headers }) .then((res) => res.data) @@ -270,54 +321,137 @@ const getUnreadCounter = async (channelName, headers) => console.log(err.message); }); -const getMentionsCounter = async (channelName, headers) => +const getRoomCounterFromId = async (id, type, headers) => await axios - .get(`${ apiEndpoints.counterurl }${ channelName }`, { + .get(`${ type === 'c' ? apiEndpoints.channelcountersidurl : apiEndpoints.groupcounterurl }${ id }`, { headers }) .then((res) => res.data) - .then((res) => `${ res.userMentions }`) .catch((err) => { console.log(err.message); + throw err; }); -const channelUnreadMessages = async (channelName, unreadCount, headers) => +const getMentionsCounter = async (channelName, headers) => await axios - .get(`${ apiEndpoints.channelmessageurl }${ channelName }`, { + .get(`${ apiEndpoints.counterurl }${ channelName }`, { headers }) .then((res) => res.data) - .then((res) => { - if (res.success === true) { + .then((res) => `${ res.userMentions }`) + .catch((err) => { + console.log(err.message); + }); - if (unreadCount == 0) { - return i18n.__('GET_UNREAD_MESSAGES_FROM_CHANNEL.NO_MESSAGE'); - } else { - const msgs = []; +const getGroupMentionsCounter = async (roomid, headers) => { + try{ + const response = await axios + .get(`${ apiEndpoints.groupcounterurl }${ roomid }`, { + headers + }) + .then((res) => res.data) + .then((res) => res.userMentions) - for (let i = 0; i <= unreadCount - 1; i++) { - msgs.push(` ${res.messages[i].u.username} says, ${res.messages[i].msg} `); - } + console.log(response) + return response; + } catch(err) { + console.log(err.message); + } +} - var responseString = msgs.join(' '); +const roomUnreadMessages = async (channelName, unreadCount, type, headers, fname = null) => { + try{ + // fname is optional and is used as a display name for discussions + // fname parameter is provided if the room is a discussion + if(fname) fname = `Discussion ${fname}` + if (!unreadCount || unreadCount == 0) { + return i18n.__('GET_UNREAD_MESSAGES_FROM_CHANNEL.NO_MESSAGE', { channelName: fname || channelName }); + } - var finalMsg = i18n.__('GET_UNREAD_MESSAGES_FROM_CHANNEL.MESSAGE', unreadCount, responseString); + // call the appropriate API endpoints depending of the type of the room + const res = await axios + .get(`${ type === 'c' ? apiEndpoints.channelmessageurl : apiEndpoints.groupmessagenameurl }${ channelName }&count=${ unreadCount }`, { + headers + }) + .then((res) => res.data) - return finalMsg; + if (res.success === true) { + + // msgs array is maintained for speech text response + const msgs = []; + // messages array is maintained to display the messages in the table as rich response + const messages = []; + + // if the same user sends multiple messages then for every message username is not mentioned + let previousUsername = ''; + for (let i = 0; i <= unreadCount - 1; i++) { + if(!res.messages[i]) { continue; } + let speechText; + + // if it's just a normal text message + if(!res.messages[i].file && !res.messages[i].t && res.messages[i].msg){ + // check if the message is not empty or made of just dots. + if(cleanMessage(res.messages[i].msg).replace(/\./g,' ').trim()) { + // speak only the text message if the same user sent the message + if(previousUsername === res.messages[i].u.username) { + msgs.push(`${res.messages[i].msg}. `) + } else { + msgs.push(`${res.messages[i].u.username} says, ${res.messages[i].msg}.`); + previousUsername = res.messages[i].u.username; + } + } + messages.push(`${res.messages[i].u.username}: ${res.messages[i].msg}`) + } else if(res.messages[i].t) { + if(res.messages[i].t === 'room_changed_description'){ + speechText = i18n.__('MESSAGE_TYPE.CHANGE_DESCRIPTION', {username: res.messages[i].u.username, description: res.messages[i].msg}) + msgs.push(speechText); + messages.push(`${res.messages[i].u.username}: ${res.messages[i].msg}`) + } else if(res.messages[i].t === 'room_changed_topic'){ + speechText = i18n.__('MESSAGE_TYPE.CHANGE_TOPIC', {username: res.messages[i].u.username, topic: res.messages[i].msg}) + msgs.push(speechText); + messages.push(`${res.messages[i].u.username}: ${res.messages[i].msg}`) + } else if(res.messages[i].t === 'room_changed_announcement'){ + speechText = i18n.__('MESSAGE_TYPE.CHANGE_ANNOUNCEMENT', {username: res.messages[i].u.username, announcement: res.messages[i].msg}) + msgs.push(speechText); + messages.push(`${res.messages[i].u.username}: ${res.messages[i].msg}`) + } else if(res.messages[i].t === 'discussion-created'){ + speechText = i18n.__('MESSAGE_TYPE.DISCUSSION_CREATED', {username: res.messages[i].u.username, name: res.messages[i].msg}) + msgs.push(speechText); + messages.push(`${res.messages[i].u.username}: ${res.messages[i].msg}`) + } + } else if(res.messages[i].file) { + if(res.messages[i].file.type.includes('image')){ + speechText = i18n.__('MESSAGE_TYPE.IMAGE_MESSAGE', {username: res.messages[i].u.username, title: res.messages[i].file.name}) + } else if (res.messages[i].file.type.includes('video')){ + speechText = i18n.__('MESSAGE_TYPE.VIDEO_MESSAGE', {username: res.messages[i].u.username, title: res.messages[i].file.name}) + }else { + speechText = i18n.__('MESSAGE_TYPE.FILE_MESSAGE', {username: res.messages[i].u.username, title: res.messages[i].file.name}) + } + msgs.push(speechText) + messages.push(`${res.messages[i].u.username}: ${res.messages[i].file.name}`) + } } + + var responseString = msgs.join(' '); + // remove the emojis, urls and special characters form speech text message + responseString = cleanMessage(responseString); + + var finalMsg = i18n.__('GET_UNREAD_MESSAGES_FROM_CHANNEL.MESSAGE',{total: unreadCount, count: msgs.length, channelName: fname || channelName, responseString }); + + // if there's nothing to display in the table just send the speech messsage. + if(messages.length === 0) return finalMsg; + + // send response as an array with first element as speech text and second element as data to be displayed in rich response + return [ finalMsg, messages ]; + } else { return i18n.__('GET_UNREAD_MESSAGES_FROM_CHANNEL.ERROR'); } - }) - .catch((err) => { - console.log(err.message); - console.log(err.message); - if (err.response.data.errorType === 'error-room-not-found') { - return i18n.__('GET_UNREAD_MESSAGES_FROM_CHANNEL.ERROR_NOT_FOUND', channelName); - } else { - return i18n.__('GET_UNREAD_MESSAGES_FROM_CHANNEL.ERROR'); - } - }); + + } catch(err) { + throw err + } +} const channelUnreadMentions = async (channelName, roomid, mentionsCount, headers) => await axios @@ -348,7 +482,6 @@ const channelUnreadMentions = async (channelName, roomid, mentionsCount, headers } }) .catch((err) => { - console.log(err.message); console.log(err.message); if (err.response.data.errorType === 'error-room-not-found') { return i18n.__('GET_USER_MENTIONS_FROM_CHANNEL.ERROR_NOT_FOUND', channelName); @@ -357,292 +490,301 @@ const channelUnreadMentions = async (channelName, roomid, mentionsCount, headers } }); -const inviteUser = async (userName, channelName, userid, roomid, headers) => - await axios - .post( - apiEndpoints.inviteuserurl, { - userId: userid, - roomId: roomid, - }, { - headers - } - ) - .then((res) => res.data) - .then((res) => { - if (res.success === true) { - return i18n.__('INVITE_USER_TO_CHANNEL.SUCCESS', userName, channelName); +const inviteUser = async (userDetails, channelDetails, headers) => { + try{ + const response = await axios + .post( + channelDetails.type === 'c' ? apiEndpoints.inviteuserurl : apiEndpoints.inviteusertogroupurl, { + userId: userDetails.id, + roomId: channelDetails.id, + }, { + headers + } + ) + .then((res) => res.data) + if (response.success === true) { + return i18n.__('INVITE_USER_TO_CHANNEL.SUCCESS', userDetails.name, channelDetails.name); } else { - return i18n.__('INVITE_USER_TO_CHANNEL.ERROR', userName, channelName); + return i18n.__('INVITE_USER_TO_CHANNEL.ERROR', userDetails.name, channelDetails.name); } - }) - .catch((err) => { - console.log(err.message); - console.log(err.message); - console.log(err.message); + } catch(err) { + console.log(err); if (err.response.data.errorType === 'error-room-not-found') { - return i18n.__('INVITE_USER_TO_CHANNEL.ERROR_NOT_FOUND', channelName); + return i18n.__('INVITE_USER_TO_CHANNEL.ERROR_NOT_FOUND', channelDetails.name); } else { - return i18n.__('INVITE_USER_TO_CHANNEL.ERROR', userName, channelName); + return i18n.__('INVITE_USER_TO_CHANNEL.ERROR', userDetails.name, channelDetails.name); } - }); + }; +} +const leaveChannel = async (channelDetails, headers) => { + try{ + const response = await axios + .post( + channelDetails.type === 'c' ? apiEndpoints.leavechannelurl : apiEndpoints.leavegroupurl, { + roomId: channelDetails.id, + }, { + headers + } + ) + .then((res) => res.data) -const leaveChannel = async (channelName, roomid, headers) => - await axios - .post( - apiEndpoints.leavechannelurl, { - roomId: roomid, - }, { - headers - } - ) - .then((res) => res.data) - .then((res) => { - if (res.success === true) { - return i18n.__('LEAVE_CHANNEl.SUCCESS', channelName); + if (response.success === true) { + return i18n.__('LEAVE_CHANNEL.SUCCESS', channelDetails.name); } else { - return i18n.__('LEAVE_CHANNEl.ERROR', channelName); + return i18n.__('LEAVE_CHANNEL.ERROR', channelDetails.name); } - }) - .catch((err) => { + }catch(err) { console.log(err.message); - return i18n.__('LEAVE_CHANNEl.ERROR', channelName); - }); + return i18n.__('LEAVE_CHANNEL.ERROR', channelDetails.name); + }; +} -const kickUser = async (userName, channelName, userid, roomid, headers) => - await axios - .post( - apiEndpoints.kickuserurl, { - userId: userid, - roomId: roomid, - }, { - headers - } - ) - .then((res) => res.data) - .then((res) => { - if (res.success === true) { - return i18n.__('KICK_USER_FROM_CHANNEL.SUCCESS', userName, channelName); +const kickUser = async (userDetails, channelDetails, headers) => { + try{ + const response = await axios + .post( + channelDetails.type === 'c' ? apiEndpoints.kickuserurl : apiEndpoints.kickuserfromgroupurl, { + userId: userDetails.id, + roomId: channelDetails.id, + }, { + headers + } + ) + .then((res) => res.data) + + if (response.success === true) { + return i18n.__('KICK_USER_FROM_CHANNEL.SUCCESS', userDetails.name, channelDetails.name); } else { - return i18n.__('KICK_USER_FROM_CHANNEL.ERROR', userName, channelName); + return i18n.__('KICK_USER_FROM_CHANNEL.ERROR', userDetails.name, channelDetails.name); } - }) - .catch((err) => { - console.log(err.message); - console.log(err.message); + }catch(err){ console.log(err.message); if (err.response.data.errorType === 'error-room-not-found') { - return i18n.__('KICK_USER_FROM_CHANNEL.ERROR_NOT_FOUND', channelName); + return i18n.__('KICK_USER_FROM_CHANNEL.ERROR_NOT_FOUND', channelDetails.name); } else { - return i18n.__('KICK_USER_FROM_CHANNEL.ERROR', userName, channelName); - } - }); - -const addLeader = async (userName, channelName, userid, roomid, headers) => - await axios - .post( - apiEndpoints.addleaderurl, { - userId: userid, - roomId: roomid, - }, { - headers - } - ) - .then((res) => res.data) - .then((res) => { - if (res.success === true) { - return i18n.__('ADD_LEADER.SUCCESS', userName, channelName); + return i18n.__('KICK_USER_FROM_CHANNEL.ERROR', userDetails.name, channelDetails.name); + } + }; +} + +const addLeader = async (userDetails, channelDetails, headers) => { + try{ + const response = await axios + .post( + channelDetails.type === 'c' ? apiEndpoints.addleaderurl : apiEndpoints.addgroupleaderurl, { + userId: userDetails.id, + roomId: channelDetails.id, + }, { + headers + } + ) + .then((res) => res.data) + + + if (response.success === true) { + return i18n.__('ADD_LEADER.SUCCESS', userDetails.name, channelDetails.name); } else { return i18n.__('ADD_LEADER.ERROR'); } - }) - .catch((err) => { + }catch(err) { console.log(err.message); - return i18n.__('ADD_LEADER.ERROR_NOT_FOUND', channelName); - }); + return i18n.__('ADD_LEADER.ERROR_NOT_FOUND', channelDetails.name); + }; +} -const channelRename = async (channelName, roomid, newName, headers) => - await axios - .post( - apiEndpoints.channelrenameurl, { - roomId: roomid, - name: newName, - }, { - headers - } - ) - .then((res) => res.data) - .then((res) => { - if (res.success === true) { - return i18n.__('RENAME_ROOM.SUCCESS', channelName, newName); +const channelRename = async (channelDetails, newName, headers) => { + try{ + const response = await axios + .post( + channelDetails.type === 'c' ? apiEndpoints.channelrenameurl : apiEndpoints.renamegroupurl, { + roomId: channelDetails.id, + name: newName, + }, { + headers + } + ) + .then((res) => res.data) + + if (response.success === true) { + return i18n.__('RENAME_ROOM.SUCCESS', channelDetails.name, newName); } else { return i18n.__('RENAME_ROOM.ERROR'); } - }) - .catch((err) => { + }catch(err){ console.log(err.message); - return i18n.__('RENAME_ROOM.ERROR_NOT_FOUND', channelName); - }); + return i18n.__('RENAME_ROOM.ERROR_NOT_FOUND', channelDetails.name); + }; +} -const unarchiveChannel = async (channelName, roomid, headers) => - await axios - .post( - apiEndpoints.unarchivechannelurl, { - roomId: roomid, - }, { - headers - } - ) - .then((res) => res.data) - .then((res) => { - if (res.success === true) { - return i18n.__('UNARCHIVE_CHANNEL.SUCCESS', channelName); +const unarchiveChannel = async (channelDetails, headers) => { + try{ + const response = await axios + .post( + channelDetails.type === 'c' ? apiEndpoints.unarchivechannelurl : apiEndpoints.unarchivegroupurl, { + roomId: channelDetails.id, + }, { + headers + } + ) + .then((res) => res.data) + + if (response.success === true) { + return i18n.__('UNARCHIVE_CHANNEL.SUCCESS', channelDetails.name); } else { return i18n.__('UNARCHIVE_CHANNEL.ERROR'); } - }) - .catch((err) => { + }catch(err){ console.log(err.message); - return i18n.__('UNARCHIVE_CHANNEL.ERROR_NOT_FOUND', channelName); - }); + return i18n.__('UNARCHIVE_CHANNEL.ERROR_NOT_FOUND', channelDetails.name); + }; +} -const channelTopic = async (channelName, roomid, topic, headers) => - await axios - .post( - apiEndpoints.channeltopicurl, { - roomId: roomid, - topic: topic, - }, { - headers - } - ) - .then((res) => res.data) - .then((res) => { - if (res.success === true) { - return i18n.__('CHANNEL_TOPIC.SUCCESS', channelName, topic); +const channelTopic = async (channelDetails, topic, headers) => { + try{ + const response = await axios + .post( + channelDetails.type === 'c' ? apiEndpoints.channeltopicurl : apiEndpoints.grouptopicurl, { + roomId: channelDetails.id, + topic: topic, + }, { + headers + } + ) + .then((res) => res.data) + + if (response.success === true) { + return i18n.__('CHANNEL_TOPIC.SUCCESS', channelDetails.name, topic); } else { return i18n.__('CHANNEL_TOPIC.ERROR'); } - }) - .catch((err) => { - console.log(err.message); - return i18n.__('CHANNEL_TOPIC.ERROR_NOT_FOUND', channelName); - }); - -const channelDescription = async (channelName, roomid, description, headers) => - await axios - .post( - apiEndpoints.channeldescriptionurl, { - roomId: roomid, - description: description, - }, { - headers - } - ) - .then((res) => res.data) - .then((res) => { - if (res.success === true) { - return i18n.__('CHANNEL_DESCRIPTION.SUCCESS', channelName, description); + }catch(err) { + console.log(err.message); + return i18n.__('CHANNEL_TOPIC.ERROR_NOT_FOUND', channelDetails.name); + }; +} + +const channelDescription = async (channelDetails, description, headers) => { + try{ + const response = await axios + .post( + channelDetails.type === 'c' ? apiEndpoints.channeldescriptionurl : apiEndpoints.groupdescriptionurl, { + roomId: channelDetails.id, + description: description, + }, { + headers + } + ) + .then((res) => res.data) + + if (response.success === true) { + return i18n.__('CHANNEL_DESCRIPTION.SUCCESS', channelDetails.name, description); } else { return i18n.__('CHANNEL_DESCRIPTION.ERROR'); } - }) - .catch((err) => { + }catch(err) { console.log(err.message); - return i18n.__('CHANNEL_DESCRIPTION.ERROR_NOT_FOUND', channelName); - }); + return i18n.__('CHANNEL_DESCRIPTION.ERROR_NOT_FOUND', channelDetails.name); + }; +} -const channelAnnouncement = async (channelName, roomid, announcement, headers) => - await axios - .post( - apiEndpoints.channelannouncementurl, { - roomId: roomid, - announcement: announcement, - }, { - headers - } - ) - .then((res) => res.data) - .then((res) => { - if (res.success === true) { - return i18n.__('CHANNEL_ANNOUNCEMENT.SUCCESS', channelName, announcement); +const setAnnouncement = async (roomDetails, announcement, headers) => { + try{ + const response = await axios + .post( + roomDetails.type == 'c' ? apiEndpoints.channelannouncementurl : apiEndpoints.groupannouncementurl, { + roomId: roomDetails.id, + announcement: announcement, + }, { + headers + } + ) + .then((res) => res.data) + + if (response.success === true) { + return i18n.__('CHANNEL_ANNOUNCEMENT.SUCCESS', roomDetails.name, announcement); } else { return i18n.__('CHANNEL_ANNOUNCEMENT.ERROR'); } - }) - .catch((err) => { - console.log(err.message); - return i18n.__('CHANNEL_ANNOUNCEMENT.ERROR_NOT_FOUND', channelName); - }); + + }catch(err){ + console.log(err.message); + return i18n.__('CHANNEL_ANNOUNCEMENT.ERROR_NOT_FOUND', channelName); + }; + } + +const removeLeader = async (userDetails, channelDetails, headers) => { + try{ + const response = await axios + .post( + channelDetails === 'c' ? apiEndpoints.removeleaderurl : apiEndpoints.removegroupleaderurl, { + userId: userDetails.id, + roomId: channelDetails.id, + }, { + headers + } + ) + .then((res) => res.data) -const removeLeader = async (userName, channelName, userid, roomid, headers) => - await axios - .post( - apiEndpoints.removeleaderurl, { - userId: userid, - roomId: roomid, - }, { - headers - } - ) - .then((res) => res.data) - .then((res) => { - if (res.success === true) { - return i18n.__('REMOVE_LEADER.SUCCESS', userName, channelName); + if (response.success === true) { + return i18n.__('REMOVE_LEADER.SUCCESS', userDetails.name, channelDetails.name); } else { return i18n.__('REMOVE_LEADER.ERROR'); } - }) - .catch((err) => { + }catch(err){ console.log(err.message); - return i18n.__('REMOVE_LEADER.ERROR_NOT_FOUND', channelName); - }); + return i18n.__('REMOVE_LEADER.ERROR_NOT_FOUND', channelDetails.name); + }; -const removeModerator = async (userName, channelName, userid, roomid, headers) => - await axios - .post( - apiEndpoints.removemoderatorurl, { - userId: userid, - roomId: roomid, - }, { - headers - } - ) - .then((res) => res.data) - .then((res) => { - if (res.success === true) { - return i18n.__('REMOVE_MODERATOR.SUCCESS', userName, channelName); +} + +const removeModerator = async (userDetails, channelDetails, headers) => { + try { + const response = await axios + .post( + channelDetails.type === 'c' ? apiEndpoints.removemoderatorurl : apiEndpoints.removegroupmoderatorurl, { + userId: userDetails.id, + roomId: channelDetails.id, + }, { + headers + } + ) + .then((res) => res.data) + + if (response.success === true) { + return i18n.__('REMOVE_MODERATOR.SUCCESS', userDetails.name, channelDetails.name); } else { return i18n.__('REMOVE_MODERATOR.ERROR'); } - }) - .catch((err) => { + }catch(err){ console.log(err.message); - return i18n.__('REMOVE_MODERATOR.ERROR_NOT_FOUND', channelName); - }); + return i18n.__('REMOVE_MODERATOR.ERROR_NOT_FOUND', channelDetails.name); + }; +} -const removeOwner = async (userName, channelName, userid, roomid, headers) => - await axios - .post( - apiEndpoints.removeownerurl, { - userId: userid, - roomId: roomid, - }, { - headers - } - ) - .then((res) => res.data) - .then((res) => { - if (res.success === true) { - return i18n.__('REMOVE_OWNER.SUCCESS', userName, channelName); +const removeOwner = async (userDetails, channelDetails, headers) => { + try{ + const response = await axios + .post( + channelDetails.type === 'c' ? apiEndpoints.removeownerurl : apiEndpoints.removegroupownerurl, { + userId: userDetails.id, + roomId: channelDetails.id, + }, { + headers + } + ) + .then((res) => res.data) + + if (response.success === true) { + return i18n.__('REMOVE_OWNER.SUCCESS', userDetails.name, channelDetails.name); } else { return i18n.__('REMOVE_OWNER.ERROR'); } - }) - .catch((err) => { + }catch(err) { console.log(err.message); - return i18n.__('REMOVE_OWNER.ERROR_NOT_FOUND', channelName); - }); + return i18n.__('REMOVE_OWNER.ERROR_NOT_FOUND', channelDetails.name); + }; +} const createDMSession = async (userName, headers) => await axios @@ -664,7 +806,7 @@ const postDirectMessage = async (message, roomid, headers) => .post( apiEndpoints.postmessageurl, { roomId: roomid, - text: message, + text: message[0].toUpperCase() + message.slice(1), //make the first letter uppercase }, { headers } @@ -889,8 +1031,6 @@ const inviteUserToGroup = async (userName, channelName, userid, roomid, headers) } }) .catch((err) => { - console.log(err.message); - console.log(err.message); console.log(err.message); if (err.response.data.errorType === 'error-room-not-found') { return i18n.__('INVITE_USER_TO_CHANNEL.ERROR_NOT_FOUND', channelName); @@ -918,8 +1058,6 @@ const kickUserFromGroup = async (userName, channelName, userid, roomid, headers) } }) .catch((err) => { - console.log(err.message); - console.log(err.message); console.log(err.message); if (err.response.data.errorType === 'error-room-not-found') { return i18n.__('KICK_USER_FROM_CHANNEL.ERROR_NOT_FOUND', channelName); @@ -1088,29 +1226,6 @@ const groupDescription = async (channelName, roomid, description, headers) => return i18n.__('CHANNEL_DESCRIPTION.ERROR_NOT_FOUND', channelName); }); -const groupAnnouncement = async (channelName, roomid, announcement, headers) => - await axios - .post( - apiEndpoints.groupannouncementurl, { - roomId: roomid, - announcement: announcement, - }, { - headers - } - ) - .then((res) => res.data) - .then((res) => { - if (res.success === true) { - return i18n.__('CHANNEL_ANNOUNCEMENT.SUCCESS', channelName, announcement); - } else { - return i18n.__('CHANNEL_ANNOUNCEMENT.ERROR'); - } - }) - .catch((err) => { - console.log(err.message); - return i18n.__('CHANNEL_ANNOUNCEMENT.ERROR_NOT_FOUND', channelName); - }); - const unarchiveGroup = async (channelName, roomid, headers) => await axios .post( @@ -1166,9 +1281,10 @@ const getGroupUnreadCounter = async (roomid, headers) => console.log(err.message); }); +// not in use const groupUnreadMessages = async (channelName, roomid, unreadCount, headers) => await axios - .get(`${ apiEndpoints.groupmessageurl }${ roomid }`, { + .get(`${ apiEndpoints.groupmessageurl }${ roomid }&count=${ unreadCount }`, { headers }) .then((res) => res.data) @@ -1181,12 +1297,14 @@ const groupUnreadMessages = async (channelName, roomid, unreadCount, headers) => const msgs = []; for (let i = 0; i <= unreadCount - 1; i++) { - msgs.push(` ${res.messages[i].u.username} says, ${res.messages[i].msg} `); + if (res.messages[i] && !res.messages[i].t){ + msgs.push(` ${res.messages[i].u.username} says, ${res.messages[i].msg}. `); + } } var responseString = msgs.join(' '); - var finalMsg = i18n.__('GET_UNREAD_MESSAGES_FROM_CHANNEL.MESSAGE', unreadCount, responseString); + var finalMsg = i18n.__('GET_UNREAD_MESSAGES_FROM_CHANNEL.MESSAGE', msgs.length, responseString); return finalMsg; } @@ -1195,7 +1313,6 @@ const groupUnreadMessages = async (channelName, roomid, unreadCount, headers) => } }) .catch((err) => { - console.log(err.message); console.log(err.message); if (err.response.data.errorType === 'error-room-not-found') { return i18n.__('GET_UNREAD_MESSAGES_FROM_CHANNEL.ERROR_NOT_FOUND', channelName); @@ -1204,6 +1321,51 @@ const groupUnreadMessages = async (channelName, roomid, unreadCount, headers) => } }); +const DMUnreadMessages = async (name, count, headers) => { + try{ + if (count == null) { + return i18n.__('GET_UNREAD_MESSAGES_FROM_CHANNEL.ERROR'); + } + if (count == 0) { + return i18n.__('GET_UNREAD_MESSAGES_FROM_DM.NO_MESSAGE', { name }); + } + + // get count number of latest messages from name username + const res = await axios + .get(`${ apiEndpoints.immessageurl }?username=${ name }&count=${ count }`, { + headers + }) + .then((res) => res.data) + + if (res.success === true) { + + const msgs = []; + + for (let i = 0; i <= count - 1; i++) { + if (res.messages[i] && !res.messages[i].t){ + if(res.messages[i].file){ + msgs.push(`Sent you a file named ${res.messages[i].file.name}.`) + } else { + if(res.messages[i].msg) msgs.push(`${res.messages[i].msg}.`); + } + } + } + + var responseString = msgs.join(' '); + responseString = cleanMessage(responseString); + + var finalMsg = i18n.__('GET_UNREAD_MESSAGES_FROM_DM.MESSAGE', {unread: msgs.length, name, responseString}); + + return [ finalMsg, msgs ]; + + } else { + return i18n.__('GET_UNREAD_MESSAGES_FROM_CHANNEL.ERROR'); + } + } catch(err) { + throw err.message; + } +} + const postGroupMessage = async (roomid, message, headers) => await axios .post( @@ -1247,6 +1409,7 @@ const getLastMessageType = async (channelName, headers) => } }); +// not in use const getLastMessageFileURL = async (channelName, headers) => await axios .get(`${ apiEndpoints.channelmessageurl }${ channelName }`, { @@ -1258,6 +1421,7 @@ const getLastMessageFileURL = async (channelName, headers) => console.log(err.message); }); +// not in use const getLastMessageFileDowloadURL = async (fileurl, headers) => await axios .get(fileurl, { @@ -1268,6 +1432,7 @@ const getLastMessageFileDowloadURL = async (fileurl, headers) => console.log(err.message); }); +// not in use const getGroupLastMessageType = async (roomid, headers) => await axios .get(`${ apiEndpoints.groupmessageurl }${ roomid }`, { @@ -1288,6 +1453,7 @@ const getGroupLastMessageType = async (roomid, headers) => } }); +// not in use const getGroupLastMessageFileURL = async (roomid, headers) => await axios .get(`${ apiEndpoints.groupmessageurl }${ roomid }`, { @@ -1299,6 +1465,607 @@ const getGroupLastMessageFileURL = async (roomid, headers) => console.log(err.message); }); +//this function resolves channel names from all the subscriptions that the user has joined. +const resolveChannelname = async (channelName, headers) => { + try { + + const subscriptions = await axios.get(apiEndpoints.getsubscriptionsurl, { + headers, + }) + .then((res) => res.data.update) + // filter only channels and groups + .then((subscriptions) => subscriptions.filter((subscription) => subscription.t === 'c' || subscription.t === 'p')) + + + if(subscriptions.length === 0) { + return null + } + + // get an array of room names to compare with the input name + let channelNames = subscriptions.map(subscription => subscription.name.replace(/\./g, ' ')) + let comparison = stringSimilar.findBestMatch(removeWhitespace(channelName).toLowerCase(), channelNames) + if(comparison.bestMatch.rating > 0.3) { + // return the best match room details in {name, id, type} format + const subscriptionDetails = subscriptions[comparison.bestMatchIndex] + return { + name: subscriptionDetails.name, + id: subscriptionDetails.rid, + type: subscriptionDetails.t + } + } else { + return null + } + + } catch (err) { + console.log(err); + } +}; + +// this function resolves the channelname to the best matching name from the latest 100 channels and latest 100 groups +// this function is faster if the user is a part of thousands of subscriptions, but comes with a limitation of comparing only from the latest 100 channels and groups. +const resolveChannelnameFromLatestRooms = async (channelName, headers) => { + try { + // sort wrt prid, so the discussions will end up at the end. + const publicChannelsResponse = await axios.get(`${apiEndpoints.channellisturl}?sort={"prid": 1, "_updatedAt": -1}&fields={"_id": 1, "name": 1, "t": 1}&count=100`, { + headers, + }).then((res) => res.data); + + const privateChannelsResponse = await axios.get(`${apiEndpoints.grouplisturl}?sort={"prid": 1, "_updatedAt": -1}&fields={"_id": 1, "name": 1, "t": 1}&count=100`, { + headers, + }).then((res) => res.data); + + // adding public channels to the array + let channels = publicChannelsResponse.channels.map((channel) => ({ + name: channel.name, + id: channel._id, + type: channel.t })); + + // adding private channels to the array + channels = channels.concat(privateChannelsResponse.groups.map((channel) => ({ + name: channel.name, + id: channel._id, + type: channel.t, + }))); + + if(channels.length === 0) { + return null + } + + let channelNames = channels.map(channel => channel.name.replace(/\./g, ' ')) + let comparison = stringSimilar.findBestMatch(removeWhitespace(channelName).toLowerCase(), channelNames) + if(comparison.bestMatch.rating > 0.3) { + return channels[comparison.bestMatchIndex] + } else { + return null + } + + } catch (err) { + console.log(err); + } +}; + +// this function resolves usernames from *all* the DMs that exist in the users contacts +const resolveUsername = async (username, headers) => { + try { + const subscriptions = await axios.get(apiEndpoints.getsubscriptionsurl, { + headers, + }) + .then((res) => res.data.update) + .then((subscriptions) => subscriptions.filter((subscription) => subscription.t === 'd')) + + if(subscriptions.length === 0){ + return null + } + + // remove the dots with spaces for better comparison + let usernames = subscriptions.map(user => user.name.replace(/\./g, ' ')) + let comparison = stringSimilar.findBestMatch(removeWhitespace(username).toLowerCase(), usernames) + if(comparison.bestMatch.rating > 0.3) { + const subscription = subscriptions[comparison.bestMatchIndex] + return { + rid: subscription.rid, // room id of the dm room + name: subscription.name, // name of the dm user + id: subscription.rid.replace(subscription.u._id, ''), // id of the user + type: subscription.t, // type of the room, 'd' in this case + } + } else { + return null + } + + } catch (err) { + console.log(err); + } +}; + +// this function resolves username from the latest 100 contacts of the user +// this function is fast if the user is a part of thousands of subscriptions, but comes with a limitation that only latest 100 users are compared +const resolveDM = async (username, currentUserDetails, headers) => { + try{ + //selects the latest 40 dm rooms in the user's contacts list + const response = await axios.get(`${apiEndpoints.imlisturl}?sort={"_updatedAt": -1}&fields={"_id": 1, "t": 1, "usernames": 1, "uids": 1}&count=100`, { + headers, + }) + .then(res => res.data.ims) + + let usernames = []; + let roomDetailsCollection = []; + + for (let room of response) { + //only consider DM's with two users + if(room.usernames.length !== 2) continue; + + // the usernames field contains two user names, [current user, other user] no fixed order. So, get index of the other user. + let indexOfUsername = 1 - room.usernames.indexOf(currentUserDetails.username) + // remove dots from the username for better comparisons + usernames.push(room.usernames[indexOfUsername].replace(/\./g, ' ')) + + let indexOfRoomId = 1 - room.uids.indexOf(currentUserDetails.id) + + roomDetailsCollection.push({ + name: room.usernames[indexOfUsername], //username of the other participant of dm + rid: room._id, //roomid of the dm room + id: room.uids[indexOfRoomId], //id of the other participant of dm + type: room.t //type of room 'd' + }) + } + + let comparison = stringSimilar.findBestMatch(removeWhitespace(username).toLowerCase(), usernames); + if(comparison.bestMatch.rating > 0.3) { + return roomDetailsCollection[comparison.bestMatchIndex] + } else { + return null + } + + }catch(err) { + console.log(err); + throw err; + } +} + +// this functions resolves either username of roomname (whichever matches best) from the subscriptions active since one week. +// this function comes with a limitation that sometimes the username and the channelname might be same. +const resolveRoomORUser = async (name, headers) => { + try{ + const no_of_days = 7; + const updatedSince = new Date(new Date().getTime() - (24 * 60 * 60 * 1000 * no_of_days)); + const subscriptions = await axios.get(`${apiEndpoints.getsubscriptionsurl}?updatedSince=${updatedSince}`, { + headers, + }) + .then((res) => res.data.update) + .then((subscriptions) => subscriptions.map((subscription) => { + if(subscription.t === 'd') { + return { + name: subscription.name, // name of the other participant in dm room + rid: subscription.rid, // id of the dm room + id: subscription.rid.replace(subscription.u._id, ''), // id of the other participant in dm room + type: subscription.t, + } + } else if(subscription.t === 'c' || subscription.t === 'p') { + return { + name: subscription.name, + id: subscription.rid, + type: subscription.t, + } + } + })) + + + let names = subscriptions.map(subscription => subscription.name.replace(/\./g, ' ')) + let comparison = stringSimilar.findBestMatch(removeWhitespace(name).toLowerCase(), names) + if(comparison.bestMatch.rating > 0.3) { + return subscriptions[comparison.bestMatchIndex] + } else { + return null + } + + }catch(err) { + console.log(err) + } +} + +// this function resolves discussion names from the latest 100 private and 100 public discussions that the user is a part of +const resolveDiscussion = async (discussionName, headers) => { + try{ + // prid sort so that the normal rooms will be considered last and discussions will appear at the top + let groupDiscussions = await axios.get(`${apiEndpoints.grouplisturl}?sort={"prid": -1, "_updatedAt": -1}&fields={"_id": 1, "name": 1, "fname": 1, "prid": 1, "t": 1}&count=100`, { + headers + }).then(res => res.data.groups); + + let channelDiscussions = await axios.get(`${apiEndpoints.channellisturl}?sort={"prid": -1, "_updatedAt": -1}&fields={"_id": 1, "name": 1, "fname": 1, "prid": 1, "t": 1}&count=100`, { + headers + }).then(res => res.data.channels); + + let discussionDetails = []; + let discussionNames = []; + + for (let discussion of groupDiscussions.concat(channelDiscussions)) { + // if prid doesn't exist it's not a discussion + if(!discussion.prid) continue; + + discussionDetails.push({ + id: discussion._id, // id of the discussion room + name: discussion.name, // the unique name of the discussion + fname: discussion.fname, // the display name of the discussion + type: discussion.t // type: private (p), public(c) + }) + + discussionNames.push(discussion.fname.toLowerCase()) + } + + if(discussionNames.length === 0) return null; + + let comparison = stringSimilar.findBestMatch(removeWhitespace(discussionName).toLowerCase(), discussionNames); + if(comparison.bestMatch.rating > 0) { + return discussionDetails[comparison.bestMatchIndex] + } else { + return null + } + } catch(err) { + console.log(err) + throw err; + } +} +const resolveUsersWithRolesFromRoom = async (recognisedUsername, channelDetails, role, headers) => { + try { + const url = channelDetails.type === 'c' ? apiEndpoints.getrolesfromchannelurl : apiEndpoints.getrolesfromgroupurl; + const response = await axios.get(`${ url }?roomId=${ channelDetails.id }`, { + headers, + }).then((res) => res.data); + + let users = []; + for (const user of response.roles) { + if (user.roles.includes(role)) { + users.push(user.u); + } + } + + users = users.map(user => { + return { + id: user._id, + name: user.username + } + }) + + let usernames = users.map(user => user.name) + + if(usernames.length === 0) { + return null + } + let comparison = stringSimilar.findBestMatch(removeWhitespace(recognisedUsername), usernames) + + if(comparison.bestMatch.rating > 0.3) { + console.log(users[comparison.bestMatchIndex]) + return users[comparison.bestMatchIndex] + } else { + return null + } + } catch (err) { + console.log(err); + if (err.response.data.errorType && err.response.data.errorType === 'error-user-not-in-room') { + return 'You are not part of this room'; + } else if (err.response.data.errorType && err.response.data.errorType === 'error-room-not-found') { + return 'no such room'; + } else if (err.response.data.errorType && err.response.data.errorType === 'error-invalid-room') { + return 'no such room'; + } else if (err.response.status === 401) { + return 'login before using this intent'; + } else { + return 'error'; + } + } + +}; + +const getLatestDiscussions = async (headers) => { + try{ + // let groupDiscussions = await axios.get(`${apiEndpoints.grouplisturl}?sort={"prid": -1, "_updatedAt": -1}&fields={"_id": 1, "name": 1, "fname": 1, "prid": 1, "t": 1}&count=100`, { + // headers + // }).then(res => res.data.groups); + + // let channelDiscussions = await axios.get(`${apiEndpoints.channellisturl}?sort={"prid": -1, "_updatedAt": -1}&fields={"_id": 1, "name": 1, "fname": 1, "prid": 1, "t": 1, "_updatedAt": 1}&count=100`, { + // headers + // }).then(res => res.data.channels); + + const no_of_days = 14; + const updatedSince = new Date(new Date().getTime() - (24 * 60 * 60 * 1000 * no_of_days)); + let subscriptions = await axios.get(`${apiEndpoints.getsubscriptionsurl}?updatedSince=${updatedSince}`, { + headers, + }).then(res => res.data.update); + + // remove subscriptions that are not discussions + subscriptions = subscriptions.filter((subscription) => subscription.prid) + + //sort them so that the lastest discussions show up at top + subscriptions.sort(compare); + + let discussionDetails = []; + + for(let discussion of subscriptions){ + // if prid doesn't exist it's not a discussion + if(!discussion.prid) continue; + + discussionDetails.push({ + id: discussion.rid, // id of the discussion room + name: discussion.name, // the unique name of the discussion + fname: discussion.fname, // the display name of the discussion + type: discussion.t // type: private (p), public(c) + }) + + } + + if(discussionDetails.length === 0) return null; + return discussionDetails; + }catch(err){ + throw err; + } +} + +function compare( a, b ) { + if ( a._updatedAt < b._updatedAt ){ + return 1; + } + if ( a._updatedAt > b._updatedAt ){ + return -1; + } + return 0; +} + +const getDMCounter = async (id, headers) => { + try { + const response = await axios.get(`${apiEndpoints.imcountersurl}?roomId=${id}`, { + headers + }) + .then((res) => res.data); + return response; + }catch(err){ + throw "Error while getting counters"; + } +} + +const getAllUnreads = async (headers) => { + try { + + const subscriptions = await axios.get(apiEndpoints.getsubscriptionsurl, { + headers, + }) + .then((res) => res.data.update); + + // finalMessage will store the final speech text + let finalMessage = ''; + // unreadDetails will store the information to be displayed in the rich response + let unreadDetails = []; + + for (const subscription of subscriptions) { + if (subscription.unread && subscription.unread !== 0) { + if(subscription.prid) { + // if the subscription is a discussion prefix it with [D] + finalMessage += `${ subscription.unread } unreads from discussion ${ subscription.fname }, `; + unreadDetails.push({name: `[D] ${subscription.fname.slice(0, 20)}`, unreads: subscription.unread}) + continue; + } + if (subscription.t && subscription.t === 'd') { + finalMessage += `${ subscription.unread } unreads from ${ subscription.name }, `; + } else { + finalMessage += `${ subscription.unread } unreads in ${ subscription.name }, `; + } + // prefic public channel with [C], private channels with [P] and direct messages with [DM] + unreadDetails.push({name: `[${subscription.t === 'd' ? 'DM' : subscription.t.toUpperCase()}] ${subscription.name.slice(0, 20)}`, unreads: subscription.unread}) + } + } + + if (finalMessage === '') { return [i18n.__('GET_ALL_UNREADS.NO_UNREADS'), []]; } + return [i18n.__('GET_ALL_UNREADS.MESSAGE', { message: finalMessage }), unreadDetails]; + } catch (err) { + console.log(err.message); + return [i18n.__('GET_ALL_UNREADS.ERROR'), []]; + } +}; + +const getAllUnreadMentions = async (headers) => { + try { + const no_of_days = 14; + const updatedSince = new Date(new Date().getTime() - (24 * 60 * 60 * 1000 * no_of_days)); + const subscriptions = await axios.get(`${apiEndpoints.getsubscriptionsurl}?updatedSince=${updatedSince}`, { + headers, + }) + .then((res) => res.data.update); + let finalMessage = ''; + let unreadDetails = []; + + for (const subscription of subscriptions) { + if (subscription.userMentions && subscription.userMentions !== 0) { + if(subscription.prid) { + finalMessage += `${ subscription.userMentions } unreads from discussion ${ subscription.fname }, `; + unreadDetails.push({name: `[D] ${subscription.fname.slice(0, 20)}`, mentions: subscription.userMentions}) + continue; + } + if (subscription.t && subscription.t === 'd') { + finalMessage += `${ subscription.userMentions } mentions from ${ subscription.name },`; + } else { + finalMessage += `${ subscription.userMentions } mentions in ${ subscription.name },`; + } + unreadDetails.push({name: `[${subscription.t === 'd' ? 'DM' : subscription.t.toUpperCase()}] ${subscription.name.slice(0, 20)}`, mentions: subscription.userMentions}) + } + } + + if (finalMessage === '') { return [i18n.__('GET_ALL_UNREAD_MENTIONS.NO_MENTIONS'), []] } + return [i18n.__('GET_ALL_UNREAD_MENTIONS.MESSAGE', { message: finalMessage }), unreadDetails]; + } catch (err) { + console.log(err.message); + return [i18n.__('GET_ALL_UNREAD_MENTIONS.ERROR'), []]; + } +}; + +const readUnreadMentions = async (channelDetails, count, headers, fname = undefined) => { + try { + if(fname) fname = `Discussion ${fname}`; + if(count === null){ + return i18n.__('MENTIONS.ERROR'); + } + if (count == 0) { + return i18n.__('MENTIONS.NO_MENTIONS', { roomName: fname || channelDetails.name }); + } + + const response = await axios.get(`${ apiEndpoints.getmentionedmessagesurl }?roomId=${ channelDetails.id }&count=${ count }`, { + headers, + }).then((res) => res.data); + + if (response.success === true) { + let finalMessage = ''; + let messages = [] + + response.messages.forEach((message) => { + finalMessage += `${ message.u.username } says, ${ message.msg }.`; + messages.push(`${ message.u.username }: ${ message.msg }.`) + }); + + finalMessage = cleanMessage(finalMessage); + + let speechText = i18n.__('MENTIONS.READ_MENTIONS', { + finalMessage, count, roomName: fname || channelDetails.name, + }) + + // if there's nothing to display in the table just return speech text + if(messages.length === 0) return speechText; + + return [ speechText, messages ]; + } else { + return i18n.__('MENTIONS.ERROR'); + } + + } catch (err) { + return i18n.__('MENTIONS.ERROR'); + } +}; + +const getAccountSummary = async (headers) => { + try { + const no_of_days = 1; + const updatedSince = new Date(new Date().getTime() - (24 * 60 * 60 * 1000 * no_of_days)); + const subscriptions = await axios.get(`${apiEndpoints.getsubscriptionsurl}?updatedSince=${updatedSince}`, { + headers, + }) + .then((res) => res.data.update); + + let summary = []; + + for (const subscription of subscriptions) { + if ((subscription.unread && subscription.unread !== 0) || (subscription.userMentions && subscription.userMentions !== 0)) { + if(subscription.prid){ + // if it is a discussion, show the displaly name instead + summary.push([`[D] ${subscription.fname.slice(0, 20)}`, `${subscription.unread}` , `${subscription.userMentions}`]) + } else { + summary.push([`[${subscription.t === 'd' ? 'DM' : subscription.t.toUpperCase()}] ${subscription.name.slice(0, 20)}`, `${subscription.unread}` , `${subscription.userMentions}`]) + } + } + } + + return summary; + } catch (err) { + console.log(err.message); + throw err; + } +} + +const cleanMessage = (string) => { + + // :([a-z_]+): => regex for emoji :emoji: + // (&[#0-9A-Za-z]*;) => regex for special character encodings &#ab3; + // ((https?|ftp):\/\/[\.[a-zA-Z0-9\/\-]+) => regex for url + + let combined_regex = new RegExp(':([a-z_]+):|(&[#0-9A-Za-z]*;)|((https?|ftp):\/\/[.[a-zA-Z0-9\/-]+)|[^ .,A-Za-z0-9\\n]', 'g'); + return string.replace(combined_regex, ''); +} + +const DMUnreadMentions = async (DMDetails, count, headers) => { + try{ + if(count == null) { + throw 'Null unreads'; + } + if (count == 0) { + return i18n.__('MENTIONS.NO_DM_MENTIONS', { name: DMDetails.name }); + } + + const response = await axios.get(`${ apiEndpoints.getmentionedmessagesurl }?roomId=${ DMDetails.rid }&count=${ count }`, { + headers, + }).then((res) => res.data); + + if (response.success === true) { + let finalMessage = ''; + let messages = []; + + response.messages.forEach((message) => { + finalMessage += `${ message.msg }.`; + messages.push(`${ message.u.username }: ${ message.msg }.`) + }); + + finalMessage = cleanMessage(finalMessage); + const speechText = i18n.__('MENTIONS.READ_DM_MENTIONS', { + finalMessage, count, name: DMDetails.name, + }); + + //if there are no important messages just return the speech text. + if(messages.length === 0) return speechText + return [ speechText, messages ]; + } else { + return i18n.__('MENTIONS.ERROR'); + } + } catch(err){ + throw err; + } +} + +const randomProperty = function(obj) { + if (typeof obj === 'string') { + return obj; + } else { + const keys = Object.keys(obj); + return obj[keys[keys.length * Math.random() << 0]]; + } +}; + +const setStatus = async (message, headers) => { + try { + const response = await axios.post(apiEndpoints.setstatusurl, { + message, + }, { + headers, + }).then((res) => res.data); + + if (response.success) { + return i18n.__('STATUS.SUCCESS'); + } + return i18n.__('STATUS.ERROR'); + } catch (err) { + console.log(err); + return i18n.__('STATUS.ERROR'); + } +}; + +const hasCommonElement = (arr1, arr2) => { + let set = new Set(arr1) + for (let element of arr2){ + if (set.has(element)){ + return true + } + } + return false +} + +const getLastMessage = async (channelDetails, headers) => { + try{ + const url = channelDetails.type === 'c' ? apiEndpoints.channelmessageurl : apiEndpoints.groupmessageurlname; + const response = await axios.get(`${url}${channelDetails.name}&count=1`, { + headers + }) + .then(res => res.data.messages[0]) + + return response + }catch(err) { + console.log(err); + } +} + // Module Export of Functions module.exports.login = login; @@ -1317,7 +2084,8 @@ module.exports.replaceWhitespacesDots = replaceWhitespacesDots; module.exports.emojiTranslateFunc = emojiTranslateFunc; module.exports.getUnreadCounter = getUnreadCounter; module.exports.getMentionsCounter = getMentionsCounter; -module.exports.channelUnreadMessages = channelUnreadMessages; +module.exports.getGroupMentionsCounter = getGroupMentionsCounter; +module.exports.roomUnreadMessages = roomUnreadMessages; module.exports.channelUnreadMentions = channelUnreadMentions; module.exports.inviteUser = inviteUser; module.exports.leaveChannel = leaveChannel; @@ -1327,7 +2095,7 @@ module.exports.channelRename = channelRename; module.exports.unarchiveChannel = unarchiveChannel; module.exports.channelTopic = channelTopic; module.exports.channelDescription = channelDescription; -module.exports.channelAnnouncement = channelAnnouncement; +module.exports.setAnnouncement = setAnnouncement; module.exports.removeLeader = removeLeader; module.exports.removeModerator = removeModerator; module.exports.removeOwner = removeOwner; @@ -1351,7 +2119,6 @@ module.exports.removeGroupOwner = removeGroupOwner; module.exports.groupRename = groupRename; module.exports.groupTopic = groupTopic; module.exports.groupDescription = groupDescription; -module.exports.groupAnnouncement = groupAnnouncement; module.exports.unarchiveGroup = unarchiveGroup; module.exports.groupLastMessage = groupLastMessage; module.exports.getGroupUnreadCounter = getGroupUnreadCounter; @@ -1361,4 +2128,26 @@ module.exports.getLastMessageType = getLastMessageType; module.exports.getLastMessageFileURL = getLastMessageFileURL; module.exports.getLastMessageFileDowloadURL = getLastMessageFileDowloadURL; module.exports.getGroupLastMessageType = getGroupLastMessageType; -module.exports.getGroupLastMessageFileURL = getGroupLastMessageFileURL; \ No newline at end of file +module.exports.getGroupLastMessageFileURL = getGroupLastMessageFileURL; +module.exports.resolveChannelname = resolveChannelname; +module.exports.resolveUsername = resolveUsername; +module.exports.getAllUnreads = getAllUnreads; +module.exports.getAllUnreadMentions = getAllUnreadMentions; +module.exports.readUnreadMentions = readUnreadMentions; +module.exports.userDetails = userDetails; +module.exports.getAccountSummary = getAccountSummary; +module.exports.resolveRoomORUser = resolveRoomORUser; +module.exports.DMUnreadMessages = DMUnreadMessages; +module.exports.getDMCounter = getDMCounter; +module.exports.DMUnreadMentions = DMUnreadMentions; +module.exports.resolveDM = resolveDM; +module.exports.getCurrentUserDetails = getCurrentUserDetails; +module.exports.resolveDiscussion = resolveDiscussion; +module.exports.getRoomCounterFromId = getRoomCounterFromId; +module.exports.getLatestDiscussions = getLatestDiscussions; +module.exports.resolveUsersWithRolesFromRoom = resolveUsersWithRolesFromRoom; +module.exports.randomProperty = randomProperty; +module.exports.setStatus = setStatus; +module.exports.hasCommonElement = hasCommonElement; +module.exports.getLastMessage = getLastMessage; +module.exports.resolveChannelnameFromLatestRooms = resolveChannelnameFromLatestRooms; diff --git a/functions/index.js b/functions/index.js index 0ad2e4a..d08e2c6 100644 --- a/functions/index.js +++ b/functions/index.js @@ -7,6 +7,9 @@ const { Button, Image, MediaObject, + Table, + Suggestions, + List } = require('actions-on-google'); const functions = require('firebase-functions'); @@ -18,7 +21,7 @@ const { } = envVariables; const app = dialogflow({ - debug: true, + debug: false, clientId: CLIENT_ID }); @@ -37,12 +40,220 @@ app.middleware((conv) => { moment.locale(conv.user.locale); }); +const handleConfirmationChannelResolution = async (app, intentData) => { + app.intent(intentData.intentName, async (conv, params) => { + try{ + const accessToken = conv.user.access.token; + const headers = await helperFunctions.login(accessToken); + let channelname = params.channelname; + + var locale = conv.user.locale; + if(locale === 'hi-IN') { + channelname = await helperFunctions.hinditranslate(channelname); + } + + const channelDetails = await helperFunctions.resolveChannelname(channelname, headers); + + if(!channelDetails){ + conv.ask(i18n.__('NO_ROOM', channelname)) + if(Math.random() >= 0.5) { + conv.ask(i18n.__('GENERIC_REPROMPT')) + } else { + // giving hints to the user + conv.ask([i18n.__('GENERIC_REPROMPT'), i18n.__('HINTS_TRANSITION'), helperFunctions.randomProperty(i18n.__('HINTS'))].join(' ')) + } + return + } + + intentData.confirmationLogic({conv, params, channelDetails, headers}) + conv.ask(new Suggestions(['yes', 'no'])) + }catch(err){ + conv.ask(i18n.__('TRY_AGAIN')); + } + }) +} + +const handleExecutionChannelResolution = async (app, intentData) => { + app.intent(intentData.intentName, async(conv, params) => { + try{ + const accessToken = conv.user.access.token; + const headers = await helperFunctions.login(accessToken); + await intentData.executionLogic({conv, params, headers}) + const random = Math.random() + if(random >= 0.7) { + conv.ask(i18n.__('GENERIC_REPROMPT')) + } else { + conv.ask([i18n.__('GENERIC_REPROMPT'), i18n.__('HINTS_TRANSITION'), helperFunctions.randomProperty(i18n.__('HINTS'))].join(' ')) + } + }catch(err){ + conv.ask(i18n.__('TRY_AGAIN')); + } + }) +} + +app.intent('Default Welcome Intent', async (conv) => { + try{ + const accessToken = conv.user.access.token; + const currentUserDetails = await helperFunctions.getCurrentUserDetails(accessToken); + if(!currentUserDetails) { + throw "Authentication Failed" + } -app.intent('Default Welcome Intent', (conv) => { + if(!conv.surface.capabilities.has('actions.capability.SCREEN_OUTPUT')){ + conv.ask(i18n.__('WELCOME.SUCCESS')); + conv.add(new Suggestions("What can you do?")) + } else { + const summary = await helperFunctions.getAccountSummary(currentUserDetails.headers); + conv.ask(i18n.__('WELCOME.SUCCESS')); + conv.add(new Suggestions(['What can you do?', 'Send direct message', 'Get my mentions'])) + + if(summary && summary.length === 0){ + //if the user has no summary to display show a simple card with profile details + conv.ask(new BasicCard({ + text: `Your Account Details`, + subtitle: currentUserDetails.userDetails.statusText, + title: currentUserDetails.userDetails.username, + image: new Image({ + url: `${currentUserDetails.userDetails.avatarUrl}`, + alt: currentUserDetails.userDetails.username, + }), + display: 'CROPPED', + })); + }else if(summary) { + //if the user has a summary to display, show a table instead + let rows = [] + for (let detail of summary) { + rows.push({ cells: detail}) + } + + conv.ask(new Table({ + title: currentUserDetails.userDetails.username, + subtitle: 'Your Account Summary (24hrs)', + image: new Image({ + url: currentUserDetails.userDetails.avatarUrl, + alt: currentUserDetails.userDetails.username + }), + columns: [ + { + header: 'Subscriptions', + align: 'LEFT', + }, + { + header: 'Unreads', + align: 'CENTER', + }, + { + header: 'Mentions', + align: 'CENTER', + }, + ], + rows: rows, + })) + } + } + + }catch(err) { + console.log(err) + conv.close(i18n.__('SOMETHING_WENT_WRONG')); + } +}); + +const handleConfirmationUserAndChannelResolution = async (app, intentData) => { + app.intent(intentData.intentName, async (conv, params) => { + const accessToken = conv.user.access.token; + const headers = await helperFunctions.login(accessToken); + let channelname = params.channelname; + let username = params.username; + + var locale = conv.user.locale; + if(locale === 'hi-IN') { + channelname = await helperFunctions.hinditranslate(channelname); + username = await helperFunctions.hinditranslate(username); + } + + const channelDetails = await helperFunctions.resolveChannelname(channelname, headers); + const userDetails = await helperFunctions.resolveUsername(username, headers); + + if(!userDetails){ + conv.ask(i18n.__('NO_USER', username)) + conv.ask(i18n.__('GENERIC_REPROMPT')) + } else if(!channelDetails){ + conv.ask(i18n.__('NO_ROOM', channelname)) + conv.ask(i18n.__('GENERIC_REPROMPT')) + } else { + conv.ask(i18n.__(`${intentData.intentResource}.CONFIRM_INTENT`, userDetails.name, channelDetails.name)) + conv.data.channelDetails = channelDetails + conv.data.userDetails = userDetails + conv.contexts.set(intentData.intentContext, 1, {channelname, username}) + conv.ask(new Suggestions(["yes", "no"])) + } + }) +} + +handleConfirmationUserAndChannelResolution(app, {intentName: 'Add Leader Intent Slot Collection', intentResource: 'ADD_LEADER', intentContext: 'add_leader'}); +handleConfirmationUserAndChannelResolution(app, {intentName: 'Add Moderator Intent Slot Collection', intentResource: 'MAKE_MODERATOR', intentContext: 'add_moderator'}); +handleConfirmationUserAndChannelResolution(app, {intentName: 'Add Owner Intent Slot Collection', intentResource: 'ADD_OWNER', intentContext: 'add_owner'}); +handleConfirmationUserAndChannelResolution(app, {intentName: 'Invite User Intent Slot Collection', intentResource: 'INVITE_USER_TO_CHANNEL', intentContext: 'invite_user'}); +handleConfirmationUserAndChannelResolution(app, {intentName: 'Kick User Intent Slot Collection', intentResource: 'KICK_USER_FROM_CHANNEL', intentContext: 'kick_user'}); + +const handleConfirmationUserWithRoleAndChannelResolution = async (app, intentData) => { + app.intent(intentData.intentName, async (conv, params) => { + const accessToken = conv.user.access.token; + const headers = await helperFunctions.login(accessToken); + let channelname = params.channelname; + let username = params.username; + + var locale = conv.user.locale; + if(locale === 'hi-IN') { + channelname = await helperFunctions.hinditranslate(channelname); + username = await helperFunctions.hinditranslate(username); + } + + const channelDetails = await helperFunctions.resolveChannelname(channelname, headers); + if(!channelDetails){ + conv.ask(i18n.__('NO_ROOM', channelname)) + conv.ask(i18n.__('GENERIC_REPROMPT')) + return + } - conv.ask(i18n.__('WELCOME.SUCCESS')); + const userDetails = await helperFunctions.resolveUsersWithRolesFromRoom(username, channelDetails, intentData.role, headers); + + if(!userDetails){ + conv.ask(i18n.__('NO_USER_WITH_ROLE', {role: intentData.role, username, channelname: channelDetails.name})) + conv.ask(i18n.__('GENERIC_REPROMPT')) + } else { + conv.ask(i18n.__(`${intentData.intentResource}.CONFIRM_INTENT`, {username: userDetails.name, role: intentData.role, channelname: channelDetails.name})) + conv.ask(new Suggestions(["yes", "no"])) + conv.data.channelDetails = channelDetails + conv.data.userDetails = userDetails + conv.contexts.set(intentData.intentContext, 1, {channelname, username}) + } + }) +} -}); +handleConfirmationUserWithRoleAndChannelResolution(app, {intentName: 'Remove Leader Intent Slot Collection', intentResource: 'REMOVE_LEADER', intentContext: 'remove_leader', role: 'leader'}) +handleConfirmationUserWithRoleAndChannelResolution(app, {intentName: 'Remove Owner Intent Slot Collection', intentResource: 'REMOVE_OWNER', intentContext: 'remove_owner', role: 'owner'}) +handleConfirmationUserWithRoleAndChannelResolution(app, {intentName: 'Remove Moderator Intent Slot Collection', intentResource: 'REMOVE_MODERATOR', intentContext: 'remove_moderator', role: 'moderator'}) + +const handleExecutionUserAndChannelResolution = async (app, {intentName, helperFunction}) => { + app.intent(intentName, async(conv, params) => { + var accessToken = conv.user.access.token; + const headers = await helperFunctions.login(accessToken); + + const speechText = await helperFunction(conv.data.userDetails, conv.data.channelDetails, headers); + conv.ask(speechText); + conv.ask(i18n.__('GENERIC_REPROMPT')) + }) +} + +handleExecutionUserAndChannelResolution(app, {intentName: 'Add Leader Intent Confirmed', helperFunction: helperFunctions.addLeader}) +handleExecutionUserAndChannelResolution(app, {intentName: 'Add Moderator Intent Confirmed', helperFunction: helperFunctions.makeModerator}) +handleExecutionUserAndChannelResolution(app, {intentName: 'Add Owner Intent Confirmed', helperFunction: helperFunctions.addOwner}) +handleExecutionUserAndChannelResolution(app, {intentName: 'Invite User Intent Confirmed', helperFunction: helperFunctions.inviteUser}) +handleExecutionUserAndChannelResolution(app, {intentName: 'Kick User Intent Confirmed', helperFunction: helperFunctions.kickUser}) +handleExecutionUserAndChannelResolution(app, {intentName: 'Remove Leader Intent Confirmed', helperFunction: helperFunctions.removeLeader}) +handleExecutionUserAndChannelResolution(app, {intentName: 'Remove Owner Intent Confirmed', helperFunction: helperFunctions.removeOwner}) +handleExecutionUserAndChannelResolution(app, {intentName: 'Remove Moderator Intent Confirmed', helperFunction: helperFunctions.removeModerator}) app.intent('Create Channel Intent', async (conv, params) => { @@ -79,6 +290,17 @@ app.intent('Create Channel Intent', async (conv, params) => { }); +handleConfirmationChannelResolution(app, {intentName: 'Delete Channel Intent Slot Collection', confirmationLogic: ({conv, channelDetails}) => { + conv.ask(i18n.__(`DELETE_CHANNEL.CONFIRM_INTENT`, { roomname: channelDetails.name })) + conv.data.channelDetails = channelDetails + conv.contexts.set('delete_channel', 1, {channelname: channelDetails.name}) +}}) + +handleExecutionChannelResolution(app, {intentName: 'Delete Channel Intent Confirmed', executionLogic: async ({conv, headers}) => { + const speechText = await helperFunctions.deleteChannel(conv.data.channelDetails, headers); + conv.ask(speechText); +}}) + app.intent('Delete Channel Intent', async (conv, params) => { var locale = conv.user.locale; @@ -114,44 +336,131 @@ app.intent('Delete Channel Intent', async (conv, params) => { }); -app.intent('Post Channel Message Intent', async (conv, params) => { +app.intent('Post Channel Message Intent Slot Collection', async (conv, params) => { + const accessToken = conv.user.access.token; + const headers = await helperFunctions.login(accessToken); + let channelname = params.channelname; + const message = params.message; var locale = conv.user.locale; + if(locale === 'hi-IN') { + channelname = await helperFunctions.hinditranslate(channelname); + } - if (locale === 'hi-IN') { + const channelDetails = await helperFunctions.resolveChannelname(channelname, headers); - var accessToken = conv.user.access.token; + if(channelDetails) { + conv.ask(i18n.__('POST_MESSAGE.CONFIRMATION', message, channelDetails.name)) + conv.data.channelDetails = channelDetails + conv.contexts.set('post_message', 1, {channelname, message}) + conv.ask(new Suggestions(["yes", "no"])) + } else { + conv.ask(i18n.__('POST_MESSAGE.NO_CHANNEL', channelname)) + conv.ask(i18n.__('GENERIC_REPROMPT')) + } +}) - var message = params.message; +app.intent('Post Channel Message Intent Confirmed', async (conv, params) => { - var channelNameRaw = params.channelname; - var channelNameData = await helperFunctions.hinditranslate(channelNameRaw); - var channelNameLwr = channelNameData.toLowerCase(); - var channelName = helperFunctions.replaceWhitespacesFunc(channelNameLwr); + var accessToken = conv.user.access.token; - const headers = await helperFunctions.login(accessToken); - const speechText = await helperFunctions.postMessage(channelName, message, headers); + var message = params.message; - conv.ask(speechText); + const channelName = conv.data.channelDetails.name - } else { + const headers = await helperFunctions.login(accessToken); + const speechText = await helperFunctions.postMessage(channelName, message, headers); - var accessToken = conv.user.access.token; + conv.ask(speechText); + conv.ask(i18n.__('GENERIC_REPROMPT')) + conv.ask(new Suggestions("Read last message")) +}); - var message = params.message; +app.intent('Get Last Message From Channel', async (conv, params) => { + var accessToken = conv.user.access.token; + const headers = await helperFunctions.login(accessToken); + let channelname = params.channelname; + var locale = conv.user.locale; - var channelNameRaw = params.channelname; - var channelNameData = channelNameRaw.toLowerCase(); - var channelName = helperFunctions.replaceWhitespacesFunc(channelNameData); + if (locale === 'hi-IN') { + channelname = helperFunctions.hinditranslate(channelname) + } - const headers = await helperFunctions.login(accessToken); - const speechText = await helperFunctions.postMessage(channelName, message, headers); + const channelDetails = await helperFunctions.resolveChannelname(channelname, headers); - conv.ask(speechText); + if(!channelDetails) { + conv.ask(i18n.__('NO_ROOM', channelname)) + conv.ask(i18n.__('GENERIC_REPROMPT')) + return + } + const lastMessage = await helperFunctions.getLastMessage(channelDetails, headers); + let speechText; + let imageURL; + let download; + if(!lastMessage.file && !lastMessage.t){ + speechText = i18n.__('MESSAGE_TYPE.TEXT_MESSAGE', {username: lastMessage.u.username, message: lastMessage.msg}) + } else if (!lastMessage.file) { + if(lastMessage.t === 'room_changed_description'){ + speechText = i18n.__('MESSAGE_TYPE.CHANGE_DESCRIPTION', {username: lastMessage.u.username, description: lastMessage.msg}) + } else if (lastMessage.t === 'room_changed_topic'){ + speechText = i18n.__('MESSAGE_TYPE.CHANGE_TOPIC', {username: lastMessage.u.username, topic: lastMessage.msg}) + } else if (lastMessage.t === 'room_changed_announcement') { + speechText = i18n.__('MESSAGE_TYPE.CHANGE_ANNOUNCEMENT', {username: lastMessage.u.username, announcement: lastMessage.msg}) + } else { + speechText = i18n.__('MESSAGE_TYPE.UNKNOWN_MESSAGE', {username: lastMessage.u.username}) + } + } else if (lastMessage.file) { + if(lastMessage.file.type.includes('image')){ + speechText = i18n.__('MESSAGE_TYPE.IMAGE_MESSAGE', {username: lastMessage.u.username, title: lastMessage.attachments[0].title}) + imageURL = await helperFunctions.getLastMessageFileDowloadURL(`${SERVER_URL}${lastMessage.attachments[0].image_url}`, headers) + } else if (lastMessage.file.type.includes('video')){ + speechText = i18n.__('MESSAGE_TYPE.VIDEO_MESSAGE', {username: lastMessage.u.username, title: lastMessage.attachments[0].title}) + download = await helperFunctions.getLastMessageFileDowloadURL(`${SERVER_URL}${lastMessage.attachments[0].title_link}`, headers) + }else { + speechText = i18n.__('MESSAGE_TYPE.FILE_MESSAGE', {username: lastMessage.u.username, title: lastMessage.attachments[0].title}) + download = await helperFunctions.getLastMessageFileDowloadURL(`${SERVER_URL}${lastMessage.attachments[0].title_link}`, headers) + } + } else { + speechText = i18n.__('MESSAGE_TYPE.UNKNOWN_MESSAGE', {username: lastMessage.u.username}) + } + conv.ask(speechText) + const url = `${SERVER_URL}/${channelDetails.type === 'c' ? 'channel' : 'group'}/${channelDetails.name}` + if(imageURL){ + conv.ask(new BasicCard({ + text: `${lastMessage.attachments[0].title}`, + buttons: new Button({ + title: 'Open in Browser', + url: `${url}`, + }), + image: new Image({ + url: `${imageURL}`, + alt: 'Rocket Chat Image Message', + }), + display: 'CROPPED', + })); + } else if(download) { + conv.ask(new BasicCard({ + title: `Message from ${lastMessage.u.username}`, + subtitle: `${ lastMessage.attachments[0].title}`, + buttons: new Button({ + title: 'View File', + url: `${download}`, + }) + })); + } else { + conv.ask(new BasicCard({ + title: `Message from ${lastMessage.u.username}`, + subtitle: lastMessage.msg || '', + buttons: new Button({ + title: 'Open in Browser', + url: `${url}`, + }) + })); } + conv.ask(i18n.__('GENERIC_REPROMPT')) -}); +}) app.intent('Channel Last Message Intent', async (conv, params) => { @@ -418,6 +727,17 @@ app.intent('Add All To Channel Intent', async (conv, params) => { }); +handleConfirmationChannelResolution(app, {intentName: 'Archive Channel Intent Slot Collection', confirmationLogic: ({conv, channelDetails}) => { + conv.ask(i18n.__(`ARCHIVE_CHANNEL.CONFIRM_INTENT`, { roomname: channelDetails.name })) + conv.data.channelDetails = channelDetails + conv.contexts.set('archive_channel', 1, {channelname: channelDetails.name}) +}}) + +handleExecutionChannelResolution(app, {intentName: 'Archive Channel Intent Confirmed', executionLogic: async ({conv, headers}) => { + const speechText = await helperFunctions.archiveChannel(conv.data.channelDetails, headers); + conv.ask(speechText); +}}) + app.intent('Archive Channel Intent', async (conv, params) => { var locale = conv.user.locale; @@ -455,43 +775,435 @@ app.intent('Archive Channel Intent', async (conv, params) => { }); -app.intent('Channel Unread Messages Intent', async (conv, params) => { +app.intent('Get All Unread Mentions Intent', async (conv) => { + const accessToken = conv.user.access.token; + const headers = await helperFunctions.login(accessToken); + const speechText = await helperFunctions.getAllUnreadMentions(headers); + conv.ask(speechText[0]); + conv.ask(i18n.__('GENERIC_REPROMPT')); + conv.ask(new Suggestions(['Read mentions from room', 'Read mentions dicussion', 'Read mentions from user'])) + if(speechText[1].length != 0) { + const unreadsDetails = speechText[1] + let count = unreadsDetails.reduce((prev, curr) => prev + curr.mentions, 0) + + let rows = [] + for(let detail of unreadsDetails) { + let cell = { + "cells": [{ + "text": detail.name + }, { + "text": `${detail.mentions}` + }] + } + rows.push(cell); + } - var locale = conv.user.locale; + conv.add(new Table({ + "title": `${count}`, + "subtitle": "Unreads", + "columns": [{ + "header": "Room/User" + }, { + "header": "Mentions" + }], + "rows": rows + })); + } +}) - if (locale === 'hi-IN') { +app.intent('Read Unread Mentions From Channel Intent', async (conv, params) => { + try{ + const accessToken = conv.user.access.token; + const headers = await helperFunctions.login(accessToken); + let channelname = params.channelname; + + var locale = conv.user.locale; + if(locale === 'hi-IN') { + channelname = await helperFunctions.hinditranslate(channelname); + } + + const channelDetails = await helperFunctions.resolveChannelname(channelname, headers); + if(!channelDetails) { + conv.ask(i18n.__('NO_ACTIVE_ROOM', { name: channelname })) + conv.ask(i18n.__('GENERIC_REPROMPT')) + return + } + + let unreadMentionsCount; + let speechText; + if(channelDetails.type === 'c') { + unreadMentionsCount = await helperFunctions.getMentionsCounter(channelDetails.name, headers); + speechText = await helperFunctions.readUnreadMentions(channelDetails, unreadMentionsCount, headers); + } else if(channelDetails.type === 'p') { + unreadMentionsCount = await helperFunctions.getGroupMentionsCounter(channelDetails.id, headers); + speechText = await helperFunctions.readUnreadMentions(channelDetails, unreadMentionsCount, headers); + } - var accessToken = conv.user.access.token; + if(!Array.isArray(speechText)){ + conv.ask(speechText) + conv.ask(i18n.__('GENERIC_REPROMPT')) + } else { + conv.ask(speechText[0]); + conv.ask(i18n.__('GENERIC_REPROMPT')) - var channelNameRaw = params.channelname; - var channelNameData = await helperFunctions.hinditranslate(channelNameRaw); - var channelNameLwr = channelNameData.toLowerCase(); - var channelName = helperFunctions.replaceWhitespacesFunc(channelNameLwr); + let row = [] + + for (let message of speechText[1]){ + row.push([message]) + } + + conv.add(new Table({ + title: channelDetails.name, + columns: [ + { + header: 'Unread Messages', + align: 'LEFT', + }, + ], + rows: row, + })) + } + + } catch(err) { + console.log(err) + conv.ask(i18n.__('SOMETHING_WENT_WRONG')); + conv.ask(i18n.__('GENERIC_REPROMPT')) + } +}) +app.intent('Read Unread Mentions From Discussion Intent', async (conv, params) => { + try{ + const accessToken = conv.user.access.token; const headers = await helperFunctions.login(accessToken); - const unreadCount = await helperFunctions.getUnreadCounter(channelName, headers); - const speechText = await helperFunctions.channelUnreadMessages(channelName, unreadCount, headers); + let discussionname = params.discussionname; + + var locale = conv.user.locale; + if(locale === 'hi-IN') { + discussionname = await helperFunctions.hinditranslate(discussionname); + } + + const channelDetails = await helperFunctions.resolveDiscussion(discussionname, headers); + if(!channelDetails) { + conv.ask(i18n.__('NO_ACTIVE_DISCUSSION', { name: discussionname })) + conv.ask(i18n.__('GENERIC_REPROMPT')) + conv.ask(new Suggestions(['Send message discussion', 'List my dicussions'])) + return + } + + let unreadMentionsCount; + let speechText; + if(channelDetails.type === 'c') { + unreadMentionsCount = await helperFunctions.getMentionsCounter(channelDetails.name, headers); + speechText = await helperFunctions.readUnreadMentions(channelDetails, unreadMentionsCount, headers, channelDetails.fname); + } else if(channelDetails.type === 'p') { + unreadMentionsCount = await helperFunctions.getGroupMentionsCounter(channelDetails.id, headers); + speechText = await helperFunctions.readUnreadMentions(channelDetails, unreadMentionsCount, headers, channelDetails.fname); + } - conv.ask(speechText); + if(!Array.isArray(speechText)){ + conv.ask(speechText) + conv.ask(i18n.__('GENERIC_REPROMPT')) + } else { + conv.ask(speechText[0]); + conv.ask(i18n.__('GENERIC_REPROMPT')) - } else { + let row = [] - var accessToken = conv.user.access.token; + for (let message of speechText[1]){ + row.push([message]) + } + + conv.add(new Table({ + title: channelDetails.fname, + columns: [ + { + header: 'Unread Messages', + align: 'LEFT', + }, + ], + rows: row, + })) + } + + } catch(err) { + console.log(err) + conv.ask(i18n.__('SOMETHING_WENT_WRONG')); + conv.ask(i18n.__('GENERIC_REPROMPT')) + } +}) + +app.intent('Read Unread Mentions From DM Intent', async (conv, params) => { + try{ + const accessToken = conv.user.access.token; + const currentUserDetails = await helperFunctions.getCurrentUserDetails(accessToken); + let username = params.username; + + var locale = conv.user.locale; + if(locale === 'hi-IN') { + username = await helperFunctions.hinditranslate(username); + } + + const DMDetails = await helperFunctions.resolveUsername(username, currentUserDetails.headers); + if(!DMDetails) { + conv.ask(i18n.__('NO_ACTIVE_USER', { username })) + conv.ask(i18n.__('GENERIC_REPROMPT')) + conv.ask(new Suggestions(['Read unreads from direct', 'get my mentions'])) + return + } + + const DMCount = await helperFunctions.getDMCounter(DMDetails.rid, currentUserDetails.headers); + let unreadMentionsCount = DMCount.userMentions + let speechText = await helperFunctions.DMUnreadMentions(DMDetails, unreadMentionsCount, currentUserDetails.headers); + + if(!Array.isArray(speechText)){ + conv.ask(speechText) + conv.ask(i18n.__('GENERIC_REPROMPT')) + } else { + conv.ask(speechText[0]); + conv.ask(i18n.__('GENERIC_REPROMPT')) - var channelNameRaw = params.channelname; - var channelNameData = channelNameRaw.toLowerCase(); - var channelName = helperFunctions.replaceWhitespacesFunc(channelNameData); + let row = [] - const headers = await helperFunctions.login(accessToken); - const unreadCount = await helperFunctions.getUnreadCounter(channelName, headers); - const speechText = await helperFunctions.channelUnreadMessages(channelName, unreadCount, headers); + for (let message of speechText[1]){ + row.push([message]) + } + + conv.add(new Table({ + title: DMDetails.name, + columns: [ + { + header: 'Unread Messages', + align: 'LEFT', + }, + ], + rows: row, + })) + } - conv.ask(speechText); + conv.ask(new Suggestions(['get my mentions', 'List my discussions'])) + + } catch(err) { + console.log(err) + conv.ask(i18n.__('SOMETHING_WENT_WRONG')); + conv.ask(i18n.__('GENERIC_REPROMPT')) + } +}) + +app.intent('Get All Unread Messages Intent', async (conv) => { + const accessToken = conv.user.access.token; + const headers = await helperFunctions.login(accessToken); + const speechText = await helperFunctions.getAllUnreads(headers); + conv.ask(speechText[0]); + conv.ask(i18n.__('GENERIC_REPROMPT')) + conv.ask(new Suggestions(['Read unreads from room', 'Read unreads dicussion', 'Read unreads from direct'])) + if(speechText[1].length != 0) { + const unreadsDetails = speechText[1] + let count = unreadsDetails.reduce((prev, curr) => prev + curr.unreads, 0) + + let rows = [] + for(let detail of unreadsDetails) { + let cell = { + "cells": [{ + "text": detail.name + }, { + "text": `${detail.unreads}` + }] + } + rows.push(cell); + } + conv.add(new Table({ + "title": `${count}`, + "subtitle": "Unreads", + "columns": [{ + "header": "Room/User" + }, { + "header": "Unreads" + }], + "rows": rows + })); } +}) + +app.intent('Read Unread Messages', async (conv, params) => { + try{ + // this intent can read unread messages from channel,group or dm. + const accessToken = conv.user.access.token; + const headers = await helperFunctions.login(accessToken); + let channelname = params.channelname; + + var locale = conv.user.locale; + if(locale === 'hi-IN') { + channelname = await helperFunctions.hinditranslate(channelname); + } + + const channelDetails = await helperFunctions.resolveRoomORUser(channelname, headers); + if(!channelDetails) { + conv.ask(i18n.__('NO_ACTIVE_SUBSCRIPTION', { name: channelname })) + conv.ask(i18n.__('GENERIC_REPROMPT')) + conv.ask(new Suggestions(['Read unreads from direct', 'Read unreads dicussion'])) + return + } + + let speechText; + + if (channelDetails.type === 'c' || channelDetails.type === 'p') { + const unreadCount = await helperFunctions.getUnreadCounter(channelDetails.name, channelDetails.type, headers); + speechText = await helperFunctions.roomUnreadMessages(channelDetails.name, unreadCount, channelDetails.type, headers); + } else if (channelDetails.type === 'd') { + const DMCount = await helperFunctions.getDMCounter(channelDetails.rid, headers); + speechText = await helperFunctions.DMUnreadMessages(channelDetails.name, DMCount.unreads, headers); + } + + if(!Array.isArray(speechText)){ + conv.ask(speechText) + conv.ask(i18n.__('GENERIC_REPROMPT')) + } else { + conv.ask(speechText[0]); + conv.ask(i18n.__('GENERIC_REPROMPT')) + + let row = [] + + for (let message of speechText[1]){ + row.push([message]) + } + + conv.add(new Table({ + title: channelDetails.name, + columns: [ + { + header: 'Unread Messages', + align: 'LEFT', + }, + ], + rows: row, + })) + } + + conv.ask(new Suggestions(['Read unread mentions', 'Read mentions from user'])) + + + } catch(err) { + console.log(err) + conv.ask(i18n.__('SOMETHING_WENT_WRONG')); + conv.ask(i18n.__('GENERIC_REPROMPT')) + } +}); + +app.intent('Read Unread Messages From Channel Intent', async (conv, params) => { + try{ + const accessToken = conv.user.access.token; + const headers = await helperFunctions.login(accessToken); + let channelname = params.channelname; + + var locale = conv.user.locale; + if(locale === 'hi-IN') { + channelname = await helperFunctions.hinditranslate(channelname); + } + + const channelDetails = await helperFunctions.resolveChannelname(channelname, headers); + if(!channelDetails) { + conv.ask(i18n.__('NO_ACTIVE_ROOM', { name: channelname })) + conv.ask(i18n.__('GENERIC_REPROMPT')) + conv.ask(new Suggestions(['Read unreads from direct', 'Read unreads dicussion'])) + return + } + + let speechText; + + const unreadCount = await helperFunctions.getUnreadCounter(channelDetails.name, channelDetails.type, headers); + speechText = await helperFunctions.roomUnreadMessages(channelDetails.name, unreadCount, channelDetails.type, headers); + + if(!Array.isArray(speechText)){ + conv.ask(speechText) + conv.ask(i18n.__('GENERIC_REPROMPT')) + } else { + conv.ask(speechText[0]); + conv.ask(i18n.__('GENERIC_REPROMPT')) + + let row = [] + for (let message of speechText[1]){ + row.push([message]) + } + + conv.add(new Table({ + title: channelDetails.name, + columns: [ + { + header: 'Unread Messages', + align: 'LEFT', + }, + ], + rows: row, + })) + } + conv.ask(new Suggestions(['Read unreads from direct', 'Read unreads dicussion'])) + + + } catch(err) { + console.log(err) + conv.ask(i18n.__('SOMETHING_WENT_WRONG')); + conv.ask(i18n.__('GENERIC_REPROMPT')) + } }); +app.intent('Read Unread Messages From Discussion Intent', async (conv, params) => { + try{ + const accessToken = conv.user.access.token; + const headers = await helperFunctions.login(accessToken); + let discussionName = params.name; + + var locale = conv.user.locale; + if(locale === 'hi-IN') { + discussionName = await helperFunctions.hinditranslate(discussionName); + } + + const discussionDetails = await helperFunctions.resolveDiscussion(discussionName, headers); + if(!discussionDetails) { + conv.ask(i18n.__('NO_ACTIVE_DISCUSSION', { name: discussionName })) + conv.ask(i18n.__('GENERIC_REPROMPT')) + conv.ask(new Suggestions(['List my discussions', 'Read mentions from discussion'])) + return + } + + const unreadCount = await helperFunctions.getUnreadCounter(discussionDetails.name, discussionDetails.type, headers); + let speechText = await helperFunctions.roomUnreadMessages(discussionDetails.name, unreadCount, discussionDetails.type, headers, discussionDetails.fname); + + if(!Array.isArray(speechText)){ + conv.ask(speechText) + conv.ask(i18n.__('GENERIC_REPROMPT')) + } else { + conv.ask(speechText[0]); + conv.ask(i18n.__('GENERIC_REPROMPT')) + + let row = [] + + for (let message of speechText[1]){ + row.push([message]) + } + + conv.add(new Table({ + title: discussionDetails.fname, + columns: [ + { + header: 'Unread Messages', + align: 'LEFT', + }, + ], + rows: row, + })) + } + + conv.ask(new Suggestions(['List my discussions', 'Read unreads from a room'])) + + } catch(err) { + console.log(err) + conv.ask(i18n.__('SOMETHING_WENT_WRONG')); + conv.ask(i18n.__('GENERIC_REPROMPT')) + } +}) + app.intent('Channel User Mentions Intent', async (conv, params) => { var locale = conv.user.locale; @@ -625,6 +1337,17 @@ app.intent('Invite User Intent', async (conv, params) => { }); +handleConfirmationChannelResolution(app, {intentName: 'Leave Channel Intent Slot Collection', confirmationLogic: ({conv, channelDetails}) => { + conv.ask(i18n.__(`LEAVE_CHANNEL.CONFIRM_INTENT`, { roomname: channelDetails.name })) + conv.data.channelDetails = channelDetails + conv.contexts.set('leave_channel', 1, {channelname: channelDetails.name}) +}}) + +handleExecutionChannelResolution(app, {intentName: 'Leave Channel Intent Confirmed', executionLogic: async ({conv, headers}) => { + const speechText = await helperFunctions.leaveChannel(conv.data.channelDetails, headers); + conv.ask(speechText); +}}) + app.intent('Leave Channel Intent', async (conv, params) => { var locale = conv.user.locale; @@ -758,6 +1481,18 @@ app.intent('Add Channel Leader Intent', async (conv, params) => { }); +handleConfirmationChannelResolution(app, {intentName: 'Rename Room Intent Slot Collection', confirmationLogic: ({conv, params, channelDetails}) => { + conv.ask(i18n.__('RENAME_ROOM.CONFIRM_INTENT', { roomname: channelDetails.name, newname: helperFunctions.replaceWhitespacesFunc(params.newname) })) + conv.data.channelDetails = channelDetails + conv.contexts.set('rename_room', 1, {channelname: channelDetails.name, newname: params.newname}) +}}) + +handleExecutionChannelResolution(app, {intentName: 'Rename Room Intent Confirmed', executionLogic: async ({conv, params, headers}) => { + const newname = helperFunctions.replaceWhitespacesFunc(params.newname); + const speechText = await helperFunctions.channelRename(conv.data.channelDetails, newname, headers); + conv.ask(speechText); +}}) + app.intent('Rename Channel Intent', async (conv, params) => { var locale = conv.user.locale; @@ -804,6 +1539,17 @@ app.intent('Rename Channel Intent', async (conv, params) => { }); +handleConfirmationChannelResolution(app, {intentName: 'Unarchive Channel Intent Slot Collection', confirmationLogic: ({conv, channelDetails}) => { + conv.ask(i18n.__(`UNARCHIVE_CHANNEL.CONFIRM_INTENT`, { roomname: channelDetails.name })) + conv.data.channelDetails = channelDetails + conv.contexts.set('unarchive_channel', 1, {channelname: channelDetails.name}) +}}) + +handleExecutionChannelResolution(app, {intentName: 'Unarchive Channel Intent Confirmed', executionLogic: async ({conv, headers}) => { + const speechText = await helperFunctions.unarchiveChannel(conv.data.channelDetails, headers); + conv.ask(speechText); +}}) + app.intent('Unarchive Channel Intent', async (conv, params) => { var locale = conv.user.locale; @@ -841,6 +1587,17 @@ app.intent('Unarchive Channel Intent', async (conv, params) => { }); +handleConfirmationChannelResolution(app, {intentName: 'Change Topic Intent Slot Collection', confirmationLogic: ({conv, params, channelDetails}) => { + conv.ask(i18n.__(`CHANNEL_TOPIC.CONFIRM_INTENT`, { roomname: channelDetails.name, topic: params.topic })) + conv.data.channelDetails = channelDetails + conv.contexts.set('change_topic', 1, {channelname: channelDetails.name, topic: params.topic}) +}}) + +handleExecutionChannelResolution(app, {intentName: 'Change Topic Intent Confirmed', executionLogic: async ({conv, params, headers}) => { + const speechText = await helperFunctions.channelTopic(conv.data.channelDetails, params.topic, headers); + conv.ask(speechText); +}}) + app.intent('Channel Topic Intent', async (conv, params) => { var locale = conv.user.locale; @@ -882,6 +1639,17 @@ app.intent('Channel Topic Intent', async (conv, params) => { }); +handleConfirmationChannelResolution(app, {intentName: 'Change Description Intent Slot Collection', confirmationLogic: ({conv, params, channelDetails}) => { + conv.ask(i18n.__(`CHANNEL_DESCRIPTION.CONFIRM_INTENT`, { roomname: channelDetails.name, description: params.description })) + conv.data.channelDetails = channelDetails + conv.contexts.set('change_description', 1, {channelname: channelDetails.name, description: params.description}) +}}) + +handleExecutionChannelResolution(app, {intentName: 'Change Description Intent Confirmed', executionLogic: async ({conv, params, headers}) => { + const speechText = await helperFunctions.channelDescription(conv.data.channelDetails, params.description, headers); + conv.ask(speechText); +}}) + app.intent('Channel Description Intent', async (conv, params) => { var locale = conv.user.locale; @@ -923,45 +1691,37 @@ app.intent('Channel Description Intent', async (conv, params) => { }); -app.intent('Channel Announcement Intent', async (conv, params) => { +app.intent('Set Announcement Intent Slot Collection', async (conv, params) => { + const accessToken = conv.user.access.token; + const headers = await helperFunctions.login(accessToken); + let channelname = params.channelname; + const announcement = params.announcement; var locale = conv.user.locale; + if(locale === 'hi-IN') { + channelname = await helperFunctions.hinditranslate(channelname); + } - if (locale === 'hi-IN') { - - var accessToken = conv.user.access.token; - - var channelNameRaw = params.channelname; - var channelNameData = await helperFunctions.hinditranslate(channelNameRaw); - var channelNameLwr = channelNameData.toLowerCase(); - var channelName = helperFunctions.replaceWhitespacesFunc(channelNameLwr); - - var announcement = params.announcement; - - const headers = await helperFunctions.login(accessToken); - const roomid = await helperFunctions.getRoomId(channelName, headers); - const speechText = await helperFunctions.channelAnnouncement(channelName, roomid, announcement, headers); - - conv.ask(speechText); + const channelDetails = await helperFunctions.resolveChannelname(channelname, headers); + if(channelDetails) { + conv.ask(i18n.__('CHANNEL_ANNOUNCEMENT.CONFIRM_INTENT', announcement, channelDetails.name)) + conv.data.channelDetails = channelDetails + conv.contexts.set('set_announcement', 1, {channelname, announcement}) } else { + conv.ask(i18n.__('CHANNEL_ANNOUNCEMENT.NO_ROOM', channelname)) + conv.ask(i18n.__('GENERIC_REPROMPT')) + } +}) - var accessToken = conv.user.access.token; - - var channelNameRaw = params.channelname; - var channelNameData = channelNameRaw.toLowerCase(); - var channelName = helperFunctions.replaceWhitespacesFunc(channelNameData); - - var announcement = params.announcement; - - const headers = await helperFunctions.login(accessToken); - const roomid = await helperFunctions.getRoomId(channelName, headers); - const speechText = await helperFunctions.channelAnnouncement(channelName, roomid, announcement, headers); - - conv.ask(speechText); +app.intent('Set Announcement Intent Confirmed', async (conv, params) => { - } + var accessToken = conv.user.access.token; + const headers = await helperFunctions.login(accessToken); + const speechText = await helperFunctions.setAnnouncement(conv.data.channelDetails, params.announcement, headers); + conv.ask(speechText); + conv.ask(i18n.__('GENERIC_REPROMPT')) }); app.intent('Remove Channel Leader Intent', async (conv, params) => { @@ -1108,45 +1868,53 @@ app.intent('Remove Channel Owner Intent', async (conv, params) => { }); -app.intent('Post DM Message Intent', async (conv, params) => { - - var locale = conv.user.locale; - - if (locale === 'hi-IN') { - - var accessToken = conv.user.access.token; - - var message = params.message; - - var userNameRaw = params.username; - var userNameData = await helperFunctions.hinditranslate(userNameRaw); - var userNameLwr = userNameData.toLowerCase(); - var userName = helperFunctions.replaceWhitespacesDots(userNameLwr); - +app.intent('Post DM Message Intent Slot Collection', async (conv, params) => { + try{ + const accessToken = conv.user.access.token; const headers = await helperFunctions.login(accessToken); - const roomid = await helperFunctions.createDMSession(userName, headers); - const speechText = await helperFunctions.postDirectMessage(message, roomid, headers); - - conv.ask(speechText); + let username = params.username; + const message = params.message; + + var locale = conv.user.locale; + if(locale === 'hi-IN') { + username = await helperFunctions.hinditranslate(username); + } + + const userDetails = await helperFunctions.resolveUsername(username, headers); + + if(userDetails) { + conv.ask(i18n.__('POST_MESSAGE.CONFIRM_DM_INTENT', message, userDetails.name)) + conv.data.userDetails = userDetails + conv.contexts.set('post_dm_message', 1, {username, message}) + conv.ask(new Suggestions(['yes', 'no'])) + } else { + conv.ask(i18n.__('POST_MESSAGE.NO_USER', username)) + conv.ask(i18n.__('GENERIC_REPROMPT')) + conv.ask(new Suggestions(['post message discussion', 'post message to room'])) + } + }catch(err){ + conv.ask(i18n.__('GENERIC_REPROMPT')) + conv.ask(i18n.__('SOMETHING_WENT_WRONG')) + conv.ask(new Suggestions(['post message discussion', 'post message to room'])) + } - } else { +}) +app.intent('Post DM Message Intent Confirmed', async (conv, params) => { + try{ var accessToken = conv.user.access.token; - var message = params.message; - - var userNameRaw = params.username; - var userNameData = userNameRaw.toLowerCase(); - var userName = helperFunctions.replaceWhitespacesDots(userNameData); - + const userDetails = conv.data.userDetails const headers = await helperFunctions.login(accessToken); - const roomid = await helperFunctions.createDMSession(userName, headers); - const speechText = await helperFunctions.postDirectMessage(message, roomid, headers); - + const speechText = await helperFunctions.postDirectMessage(message, userDetails.rid, headers); conv.ask(speechText); - + conv.ask(i18n.__('GENERIC_REPROMPT')) + conv.ask(new Suggestions(['post message discussion', 'post message to room'])) + }catch(err){ + conv.ask(i18n.__('GENERIC_REPROMPT')) + conv.ask(i18n.__('SOMETHING_WENT_WRONG')) + conv.ask(new Suggestions(['post message discussion', 'post message to room'])) } - }); app.intent('Post DM Emoji Message Intent', async (conv, params) => { @@ -1891,47 +2659,6 @@ app.intent('Group Description Intent', async (conv, params) => { }); -app.intent('Group Announcement Intent', async (conv, params) => { - - var locale = conv.user.locale; - - if (locale === 'hi-IN') { - - var accessToken = conv.user.access.token; - - var channelNameRaw = params.channelname; - var channelNameData = await helperFunctions.hinditranslate(channelNameRaw); - var channelNameLwr = channelNameData.toLowerCase(); - var channelName = helperFunctions.replaceWhitespacesFunc(channelNameLwr); - - var announcement = params.announcement; - - const headers = await helperFunctions.login(accessToken); - const roomid = await helperFunctions.getGroupId(channelName, headers); - const speechText = await helperFunctions.groupAnnouncement(channelName, roomid, announcement, headers); - - conv.ask(speechText); - - } else { - - var accessToken = conv.user.access.token; - - var channelNameRaw = params.channelname; - var channelNameData = channelNameRaw.toLowerCase(); - var channelName = helperFunctions.replaceWhitespacesFunc(channelNameData); - - var announcement = params.announcement; - - const headers = await helperFunctions.login(accessToken); - const roomid = await helperFunctions.getGroupId(channelName, headers); - const speechText = await helperFunctions.groupAnnouncement(channelName, roomid, announcement, headers); - - conv.ask(speechText); - - } - -}); - app.intent('Unarchive Group Intent', async (conv, params) => { var locale = conv.user.locale; @@ -2150,7 +2877,7 @@ app.intent('Default No Input Intent', (conv) => { }; }); -app.intent('Post Group Message Intent', async (conv, params) => { +app.intent('Post Group Emoji Message Intent', async (conv, params) => { var locale = conv.user.locale; @@ -2158,13 +2885,17 @@ app.intent('Post Group Message Intent', async (conv, params) => { var accessToken = conv.user.access.token; - var message = params.message; - var channelNameRaw = params.channelname; var channelNameData = await helperFunctions.hinditranslate(channelNameRaw); var channelNameLwr = channelNameData.toLowerCase(); var channelName = helperFunctions.replaceWhitespacesFunc(channelNameLwr); + var messageData = params.message; + const emojiRaw = params.emoji; + var emojiData = await helperFunctions.hinditranslate(emojiRaw); + const emoji = helperFunctions.emojiTranslateFunc(emojiData); + const message = messageData + emoji; + const headers = await helperFunctions.login(accessToken); const roomid = await helperFunctions.getGroupId(channelName, headers); const speechText = await helperFunctions.postGroupMessage(roomid, message, headers); @@ -2175,12 +2906,15 @@ app.intent('Post Group Message Intent', async (conv, params) => { var accessToken = conv.user.access.token; - var message = params.message; - var channelNameRaw = params.channelname; var channelNameData = channelNameRaw.toLowerCase(); var channelName = helperFunctions.replaceWhitespacesFunc(channelNameData); + var messageData = params.message; + const emojiData = params.emoji; + const emoji = helperFunctions.emojiTranslateFunc(emojiData); + const message = messageData + emoji; + const headers = await helperFunctions.login(accessToken); const roomid = await helperFunctions.getGroupId(channelName, headers); const speechText = await helperFunctions.postGroupMessage(roomid, message, headers); @@ -2191,53 +2925,254 @@ app.intent('Post Group Message Intent', async (conv, params) => { }); -app.intent('Post Group Emoji Message Intent', async (conv, params) => { - - var locale = conv.user.locale; - - if (locale === 'hi-IN') { +app.intent('Post Discussion Message Intent Slot Collection', async (conv, params) => { + try{ + const accessToken = conv.user.access.token; + const headers = await helperFunctions.login(accessToken); + let discussionname = params.discussionname; + const message = params.message; + + var locale = conv.user.locale; + if(locale === 'hi-IN') { + discussionname = await helperFunctions.hinditranslate(discussionname); + } + + const discussionDetails = await helperFunctions.resolveDiscussion(discussionname, headers); + + if(discussionDetails) { + conv.ask(i18n.__('POST_MESSAGE.CONFIRM_DISCUSSION_INTENT', message, discussionDetails.fname)) + conv.data.discussionDetails = discussionDetails + conv.ask(new Suggestions(['yes', 'no'])); + conv.contexts.set('post_discussion_message', 1, {discussionname, message}) + } else { + conv.ask(i18n.__('NO_ACTIVE_DISCUSSION', {name: discussionname})) + conv.ask(i18n.__('GENERIC_REPROMPT')) + } + }catch(err){ + console.log(err) + conv.ask(i18n.__('SOMETHING_WENT_WRONG')); + conv.ask(i18n.__('GENERIC_REPROMPT')) + } +}) +app.intent('Post Discussion Message Intent Confirmed', async (conv, params) => { + try{ var accessToken = conv.user.access.token; - - var channelNameRaw = params.channelname; - var channelNameData = await helperFunctions.hinditranslate(channelNameRaw); - var channelNameLwr = channelNameData.toLowerCase(); - var channelName = helperFunctions.replaceWhitespacesFunc(channelNameLwr); - - var messageData = params.message; - const emojiRaw = params.emoji; - var emojiData = await helperFunctions.hinditranslate(emojiRaw); - const emoji = helperFunctions.emojiTranslateFunc(emojiData); - const message = messageData + emoji; - + var message = params.message; const headers = await helperFunctions.login(accessToken); - const roomid = await helperFunctions.getGroupId(channelName, headers); - const speechText = await helperFunctions.postGroupMessage(roomid, message, headers); - + const speechText = await helperFunctions.postMessage(conv.data.discussionDetails.name, message, headers); conv.ask(speechText); + conv.ask(i18n.__('GENERIC_REPROMPT')) + } catch(err){ + console.log(err) + conv.ask(i18n.__('SOMETHING_WENT_WRONG')); + conv.ask(i18n.__('GENERIC_REPROMPT')) + } +}); - } else { +app.intent('Read Unread Messages From DM Intent', async (conv, params) => { + try{ + const accessToken = conv.user.access.token; + const currentUserDetails = await helperFunctions.getCurrentUserDetails(accessToken); + let username = params.username; + + var locale = conv.user.locale; + if(locale === 'hi-IN') { + username = await helperFunctions.hinditranslate(username); + } + + const DMDetails = await helperFunctions.resolveUsername(username, currentUserDetails.headers); if(!DMDetails) { + conv.ask(i18n.__('NO_ACTIVE_USER', { username })) + conv.ask(i18n.__('GENERIC_REPROMPT')) + conv.ask(new Suggestions(['get my mentions', 'Read unreads from dicussion'])) + return + } - var accessToken = conv.user.access.token; + const DMCount = await helperFunctions.getDMCounter(DMDetails.rid, currentUserDetails.headers); + const speechText = await helperFunctions.DMUnreadMessages(DMDetails.name, DMCount.unreads, currentUserDetails.headers); - var channelNameRaw = params.channelname; - var channelNameData = channelNameRaw.toLowerCase(); - var channelName = helperFunctions.replaceWhitespacesFunc(channelNameData); + if(!Array.isArray(speechText)){ + conv.ask(speechText) + conv.ask(i18n.__('GENERIC_REPROMPT')) + } else { + conv.ask(speechText[0]); + conv.ask(i18n.__('GENERIC_REPROMPT')) - var messageData = params.message; - const emojiData = params.emoji; - const emoji = helperFunctions.emojiTranslateFunc(emojiData); - const message = messageData + emoji; + let row = [] + for (let message of speechText[1]){ + row.push([message]) + } + + conv.add(new Table({ + title: DMDetails.name, + columns: [ + { + header: 'Unread Messages', + align: 'LEFT', + }, + ], + rows: row, + })) + } + conv.ask(new Suggestions(['Read mentions from room', 'Read unreads from a dicussion'])) + + }catch(err){ + console.log(err) + conv.ask(i18n.__('SOMETHING_WENT_WRONG')); + conv.ask(i18n.__('GENERIC_REPROMPT')) + } +}) + +app.intent('List My Discussions', async (conv, params) => { + try{ + if (!conv.screen) { + conv.ask('Sorry, this only works for devices with screens'); + return; + } + var accessToken = conv.user.access.token; const headers = await helperFunctions.login(accessToken); - const roomid = await helperFunctions.getGroupId(channelName, headers); - const speechText = await helperFunctions.postGroupMessage(roomid, message, headers); + + const discussionDetails = await helperFunctions.getLatestDiscussions(headers); - conv.ask(speechText); + if(!discussionDetails) { + conv.ask('You are not part of any discussions'); + conv.ask(i18n.__('GENERIC_REPROMPT')) + return; + } - } + if(discussionDetails.length === 1) { + conv.ask(`You are part of one discussion named ${discussionDetails[0].fname}`) + conv.ask(i18n.__('GENERIC_REPROMPT')) + return; + } -}); + // generating items to display in a rich response list + const items = {}; + + for (let discussion of discussionDetails) { + //store the discussion details as the key of the list item + items[JSON.stringify(discussion)] = { + title: discussion.fname, + } + } + + conv.ask('Use this list anytime to select discussion names while using the action.'); + conv.ask(new Suggestions(['Send message discussion', 'Read unreads dicussion'])) + // Create a list + conv.ask(new List({ + title: 'Your Discussions.', + items: items, + })); + }catch(err){ + console.log(err) + conv.ask(i18n.__('SOMETHING_WENT_WRONG')); + conv.ask(i18n.__('GENERIC_REPROMPT')) + } + }); + +app.intent('Handle Touch In List', async (conv, params, option) => { + try{ + //parse the discussion details from the key of selected option + const discussionDetails = JSON.parse(option); + var accessToken = conv.user.access.token; + const headers = await helperFunctions.login(accessToken); + const counters = await helperFunctions.getRoomCounterFromId(discussionDetails.id, discussionDetails.type, headers); + + //display basic informatino of the discussion in a table + conv.ask(`You have ${counters.unreads} unreads and ${counters.userMentions} mentions in discussion ${discussionDetails.fname}`) + conv.ask(i18n.__('GENERIC_REPROMPT')) + conv.ask(new Table({ + title: 'Updates from discussion', + subtitle: discussionDetails.fname, + columns: [ + { + header: 'Unreads', + align: 'CENTER', + }, + { + header: 'User Mentions', + align: 'CENTER', + }, + ], + rows: [{ + cells: [`${counters.unreads}`, `${counters.userMentions}`] + }], + })) + }catch(err){ + console.log(err) + conv.ask(i18n.__('SOMETHING_WENT_WRONG')); + conv.ask(i18n.__('GENERIC_REPROMPT')) + } -exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app); \ No newline at end of file + }) + + +handleExecutionChannelResolution(app, {intentName: 'Change Status Intent Confirmed', executionLogic: async ({conv, params, headers}) => { + const speechText = await helperFunctions.setStatus(params.status, headers) + conv.ask(speechText); +}}) + +handleExecutionChannelResolution(app, {intentName: 'Create Channel Intent Confirmed', executionLogic: async ({conv, params, headers}) => { + let channelname = helperFunctions.replaceWhitespacesFunc(params.channelname); + const speechText = await helperFunctions.createChannel(channelname, headers); + conv.ask(speechText); +}}) + +handleExecutionChannelResolution(app, {intentName: 'Create Group Intent Confirmed', executionLogic: async ({conv, params, headers}) => { + let channelname = helperFunctions.replaceWhitespacesFunc(params.channelname); + const speechText = await helperFunctions.createGroup(channelname, headers); + conv.ask(speechText); +}}) + +app.intent('Denied Intent', (conv) => { + const contexts = [ + 'change_description', + 'change_topic', + 'rename_room', + 'archive_channel', + 'unarchive_channel', + 'change_status', + 'add_leader', + 'add_moderator', + 'add_owner', + 'invite_user', + 'kick_user', + 'leave_channel', + 'delete_channel', + 'remove_owner', + 'remove_moderator', + 'remove_leader', + 'change_status', + 'post_dm_message', + 'post_message', + 'set_announcement', + 'post_discussion_message', + 'create_channel', + 'create_group' + ] + + let inputContexts = Object.keys(conv.contexts.input) + + if(helperFunctions.hasCommonElement(contexts, inputContexts)){ + conv.ask(i18n.__('GENERIC_DENIED_MESSAGE')) + } else { + conv.close(i18n.__('GOODBYE.MESSAGE')) + } +}) + +if(process.env.DEVELOPMENT) { + // if code is running in local development environment + const express = require('express') + const bodyParser = require('body-parser') + const expressApp = express().use(bodyParser.json()) + expressApp.post('/', (app)) + expressApp.listen(3000) +} else if(Boolean(process.env['AWS_LAMBDA_FUNCTION_NAME'])) { + // if code is deployed in aws lambda function environment + exports.handler = app; +} else{ + // if code is deployed in firebase function + exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app); +} \ No newline at end of file diff --git a/functions/locales/en-AU.json b/functions/locales/en-AU.json index 2630e24..c4f2a35 100644 --- a/functions/locales/en-AU.json +++ b/functions/locales/en-AU.json @@ -12,10 +12,16 @@ }, "WELCOME": { "SUCCESS": "Welcome To Rocket Chat Google Action. What Would you like to do today?", - "ERROR": "To start using this action, please link your account to authenticate." + "ERROR": "To start using this action, please link your account to authenticate.", + "AUTH_ERROR": "Sorry, I could not connect you with your account." }, "POST_MESSAGE": { "SUCCESS": "I've sent your message.", + "CONFIRM_DISCUSSION_INTENT": "You want to send, %s, to discussion %s. Is that correct?", + "CONFIRMATION": "You want to send, %s, to room %s, is that correct?", + "NO_CHANNEL": "There is no room named %s in your subscriptions list.", + "CONFIRM_DM_INTENT": "You want to send, %s, to user, %s, is that correct?", + "NO_USER": "There is no user named %s in your contacts list.", "ERROR": "Sorry, I couldn't send your message right now." }, "CREATE_CHANNEL": { @@ -27,6 +33,7 @@ }, "DELETE_CHANNEL": { "SUCCESS": "I've deleted the channel %s.", + "CONFIRM_INTENT": "You want to delete room {{roomname}}, is that correct?", "ERROR": "Sorry, I couldn't delete the channel %s right now.", "ERROR_NOT_FOUND": "Sorry, the channel %s does not exist. Please try again with different channel name." }, @@ -39,6 +46,7 @@ }, "MAKE_MODERATOR": { "SUCCESS": "%s is now the moderator of %s.", + "CONFIRM_INTENT": "You want to make %s, as moderator of room %s, is that correct?", "ERROR": "Sorry, I couldn't assign a moderator right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't assign a moderator to %s right now." }, @@ -49,17 +57,19 @@ }, "ADD_OWNER": { "SUCCESS": "%s is now the owner of %s.", + "CONFIRM_INTENT": "You want to make %s, as an owner of room %s, is that correct?", "ERROR": "Sorry, I couldn't assign a owner to the channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't assign a owner to channel %s right now." }, "ARCHIVE_CHANNEL": { "SUCCESS": "%s is now archived.", + "CONFIRM_INTENT": "You want to archive room {{roomname}}, is that correct?", "ERROR": "Sorry, I couldn't archive this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't archive channel %s right now." }, "GET_UNREAD_MESSAGES_FROM_CHANNEL": { - "NO_MESSAGE": "You have no unread messages.", - "MESSAGE": " You Have %s Unread Messages

%s

", + "NO_MESSAGE": "You don't have any unread messages in {{channelName}}.", + "MESSAGE": " You Have {{total}} unread activities and {{count}} Unread Messages in {{channelName}}.

{{responseString}}

", "ERROR": "Sorry, I couldn't get your unread messages right now.", "ERROR_NOT_FOUND": "Sorry, the channel %s does not exist. Please try again with different channel name." }, @@ -71,61 +81,134 @@ }, "INVITE_USER_TO_CHANNEL": { "SUCCESS": "%s is invited to the channel %s ", + "CONFIRM_INTENT": "You want to invite %s, to room %s, is that correct?", "ERROR": "Sorry I couldn't invite user %s to channel %s right now", "ERROR_NOT_FOUND": "Sorry, I couldn't find channel %s right now" }, - "LEAVE_CHANNEl": { + "LEAVE_CHANNEL": { "SUCCESS": "You Left channel %s .", + "CONFIRM_INTENT": "You want to leave room {{roomname}}, is that correct?", "ERROR": "Sorry, You couldn't leave the channel %s right now. Maybe you are the only owner of Channel so first set someone as the channel owner" }, "KICK_USER_FROM_CHANNEL": { "SUCCESS": "%s is now kicked from channel %s ", + "CONFIRM_INTENT": "You want to kick %s, from room %s, is that correct?", "ERROR": "Sorry I couldn't kick user %s from channel %s right now", "ERROR_NOT_FOUND": "Sorry, I couldn't find channel %s right now" }, "ADD_LEADER": { "SUCCESS": "%s is now the leader of %s.", + "CONFIRM_INTENT": "You want to make %s, as leader of room %s, is that correct?", "ERROR": "Sorry, I couldn't assign a leader to the channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't assign a leader to channel %s right now." }, "RENAME_ROOM": { "SUCCESS": "%s is now renamed to %s.", + "CONFIRM_INTENT":"You want to rename room {{roomname}}, to {{newname}}, is that correct?", "ERROR": "Sorry, I couldn't rename this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't rename channel %s right now." }, "UNARCHIVE_CHANNEL": { "SUCCESS": "%s is now unarchived.", + "CONFIRM_INTENT":"You want to unarchive room {{roomname}}, is that correct?", "ERROR": "Sorry, I couldn't unarchive this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't unarchive channel %s right now." }, "CHANNEL_TOPIC": { "SUCCESS": "%s topic is now changed to %s", + "CONFIRM_INTENT": "You want to set topic of room, {{roomname}} as, {{topic}}, is that correct?", "ERROR": "Sorry, I couldn't change this channel topic right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't change topic for channel %s right now." }, "CHANNEL_DESCRIPTION": { "SUCCESS": "%s description is now changed to %s", + "CONFIRM_INTENT": "You want to set description of room, {{roomname}} as, {{description}}, is that correct?", "ERROR": "Sorry, I couldn't change this channel description right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't change description for channel %s right now." }, "CHANNEL_ANNOUNCEMENT": { "SUCCESS": "%s announcement is now changed to %s", + "CONFIRM_INTENT": "You want to set, %s, as announcement in room %s, is that correct?", + "NO_ROOM": "There is no room matching %s.", "ERROR": "Sorry, I couldn't change this channel announcement right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't change announcement for channel %s right now." }, "REMOVE_LEADER": { "SUCCESS": "%s is no longer the leader of %s.", + "CONFIRM_INTENT": "You want to remove {{username}}, as {{role}} of room {{channelname}}, is that correct?", "ERROR": "Sorry, I couldn't remove leader from this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't remove leader from channel %s right now." }, "REMOVE_MODERATOR": { "SUCCESS": "%s is no longer the moderator of %s.", + "CONFIRM_INTENT": "You want to remove {{username}}, as {{role}} of room {{channelname}}, is that correct?", "ERROR": "Sorry, I couldn't remove moderator from this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't remove moderator from channel %s right now." }, "REMOVE_OWNER": { "SUCCESS": "%s is no longer the owner of %s.", + "CONFIRM_INTENT": "You want to remove {{username}}, as {{role}} of room {{channelname}}, is that correct?", "ERROR": "Sorry, I couldn't remove owner from this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't remove owner from channel %s right now." - } + }, + "GET_ALL_UNREADS": { + "MESSAGE": "You have, {{message}}.", + "NO_UNREADS": "You don't have any unread messages.", + "ERROR": "Sorry, I am not able to get unread messages." + }, + "GET_ALL_UNREAD_MENTIONS": { + "MESSAGE": "You have, {{message}}.", + "NO_MENTIONS": "You don't have any unread mentions.", + "ERROR": "Sorry, I am not able to get your mentions." + }, + "GET_UNREAD_MESSAGES_FROM_DM": { + "NO_MESSAGE": "You don't have any unread messages from DM, {{name}}.", + "MESSAGE": "You have, {{unread}} unreads from {{name}}. {{responseString}}." + }, + "MENTIONS": { + "READ_MENTIONS": "You have {{count}} mentions in {{roomName}}. {{finalMessage}}.", + "NO_MENTIONS": "You don't have any mentions in {{roomName}}.", + "READ_DM_MENTIONS": "You have {{count}} mentions from {{name}}. {{finalMessage}}.", + "NO_DM_MENTIONS": "You don't have any mentions from DM, {{name}}.", + "ERROR": "Sorry, I couldn't get your mentions" + }, + "MESSAGE_TYPE": { + "TEXT_MESSAGE": "{{username}} says, {{message}}", + "CHANGE_DESCRIPTION": "{{username}} changed the description to, {{description}}.", + "CHANGE_ANNOUNCEMENT": "{{username}} made an announcement that says {{announcement}}.", + "CHANGE_TOPIC": "{{username}} changed the topic to {{topic}}.", + "IMAGE_MESSAGE": "{{username}} shared an image titled {{title}}.", + "VIDEO_MESSAGE": "{{username}} shared a video titled {{title}}.", + "FILE_MESSAGE": "{{username}} shared a file titled {{title}}.", + "DISCUSSION_CREATED": "{{username}} created a discussion named {{name}}.", + "UNKNOWN_MESSAGE": "{{username}}, performed some action" + }, + "HINTS": { + "GET_UNREADS": "Do I have any unread messages?", + "GET_UNREAD_MENTIONS": "Do I have any unread mentions?", + "READ_UNREADS_FROM_DISCUSSION": "Read unreads from a discussion", + "CHANGE_STATUS": "Change my status.", + "READ_MENTIONS_FROM_USER": "Read mentions from a user", + "LIST_DISCUSSIONS": "List my discussions", + "READ_UNREADS": "Read unreads messages from a channel.", + "CHANNEL_ANNOUNCEMENT": "Make an announcement.", + "POST_DIRECT_MESSAGE": "Send a direct message.", + "POST_DISCUSSION_MESSAGE": "Send message to a discussion." + }, + "STATUS": { + "SUCCESS": "I have changed your status.", + "ERROR": "Sorry, I could not change your status." + }, + "NO_ACTIVE_USER": "Couldn't find an active user named {{username}} from your contacts.", + "NO_ACTIVE_DISCUSSION": "Couldn't find an active discussion named {{name}} from your discussions.", + "NO_ACTIVE_ROOM": "Couldn't detect a room named {{name}}, maybe it's not active since long.", + "NO_ROOM": "You are not part of any channel or group named %s .", + "NO_ACTIVE_SUBSCRIPTION": "Couldn't detect a room or user named {{name}} from your subscriptions list. Maybe it's not active.", + "GENERIC_REPROMPT": "Anything else I can help you with?", + "SOMETHING_WENT_WRONG": "Sorry, something went wrong.", + "NO_USER": "There's no user named, %s in your contacts list.", + "NO_USER_WITH_ROLE": "There is no {{role}} named {{username}} in room {{channelname}}.", + "HINTS_TRANSITION": "You can try saying, ", + "TRY_AGAIN": "Sorry, something went wrong, can you please try again?", + "GENERIC_DENIED_MESSAGE": "Okay, Anything else I can help you with?" } \ No newline at end of file diff --git a/functions/locales/en-CA.json b/functions/locales/en-CA.json index 2630e24..c4f2a35 100644 --- a/functions/locales/en-CA.json +++ b/functions/locales/en-CA.json @@ -12,10 +12,16 @@ }, "WELCOME": { "SUCCESS": "Welcome To Rocket Chat Google Action. What Would you like to do today?", - "ERROR": "To start using this action, please link your account to authenticate." + "ERROR": "To start using this action, please link your account to authenticate.", + "AUTH_ERROR": "Sorry, I could not connect you with your account." }, "POST_MESSAGE": { "SUCCESS": "I've sent your message.", + "CONFIRM_DISCUSSION_INTENT": "You want to send, %s, to discussion %s. Is that correct?", + "CONFIRMATION": "You want to send, %s, to room %s, is that correct?", + "NO_CHANNEL": "There is no room named %s in your subscriptions list.", + "CONFIRM_DM_INTENT": "You want to send, %s, to user, %s, is that correct?", + "NO_USER": "There is no user named %s in your contacts list.", "ERROR": "Sorry, I couldn't send your message right now." }, "CREATE_CHANNEL": { @@ -27,6 +33,7 @@ }, "DELETE_CHANNEL": { "SUCCESS": "I've deleted the channel %s.", + "CONFIRM_INTENT": "You want to delete room {{roomname}}, is that correct?", "ERROR": "Sorry, I couldn't delete the channel %s right now.", "ERROR_NOT_FOUND": "Sorry, the channel %s does not exist. Please try again with different channel name." }, @@ -39,6 +46,7 @@ }, "MAKE_MODERATOR": { "SUCCESS": "%s is now the moderator of %s.", + "CONFIRM_INTENT": "You want to make %s, as moderator of room %s, is that correct?", "ERROR": "Sorry, I couldn't assign a moderator right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't assign a moderator to %s right now." }, @@ -49,17 +57,19 @@ }, "ADD_OWNER": { "SUCCESS": "%s is now the owner of %s.", + "CONFIRM_INTENT": "You want to make %s, as an owner of room %s, is that correct?", "ERROR": "Sorry, I couldn't assign a owner to the channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't assign a owner to channel %s right now." }, "ARCHIVE_CHANNEL": { "SUCCESS": "%s is now archived.", + "CONFIRM_INTENT": "You want to archive room {{roomname}}, is that correct?", "ERROR": "Sorry, I couldn't archive this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't archive channel %s right now." }, "GET_UNREAD_MESSAGES_FROM_CHANNEL": { - "NO_MESSAGE": "You have no unread messages.", - "MESSAGE": " You Have %s Unread Messages

%s

", + "NO_MESSAGE": "You don't have any unread messages in {{channelName}}.", + "MESSAGE": " You Have {{total}} unread activities and {{count}} Unread Messages in {{channelName}}.

{{responseString}}

", "ERROR": "Sorry, I couldn't get your unread messages right now.", "ERROR_NOT_FOUND": "Sorry, the channel %s does not exist. Please try again with different channel name." }, @@ -71,61 +81,134 @@ }, "INVITE_USER_TO_CHANNEL": { "SUCCESS": "%s is invited to the channel %s ", + "CONFIRM_INTENT": "You want to invite %s, to room %s, is that correct?", "ERROR": "Sorry I couldn't invite user %s to channel %s right now", "ERROR_NOT_FOUND": "Sorry, I couldn't find channel %s right now" }, - "LEAVE_CHANNEl": { + "LEAVE_CHANNEL": { "SUCCESS": "You Left channel %s .", + "CONFIRM_INTENT": "You want to leave room {{roomname}}, is that correct?", "ERROR": "Sorry, You couldn't leave the channel %s right now. Maybe you are the only owner of Channel so first set someone as the channel owner" }, "KICK_USER_FROM_CHANNEL": { "SUCCESS": "%s is now kicked from channel %s ", + "CONFIRM_INTENT": "You want to kick %s, from room %s, is that correct?", "ERROR": "Sorry I couldn't kick user %s from channel %s right now", "ERROR_NOT_FOUND": "Sorry, I couldn't find channel %s right now" }, "ADD_LEADER": { "SUCCESS": "%s is now the leader of %s.", + "CONFIRM_INTENT": "You want to make %s, as leader of room %s, is that correct?", "ERROR": "Sorry, I couldn't assign a leader to the channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't assign a leader to channel %s right now." }, "RENAME_ROOM": { "SUCCESS": "%s is now renamed to %s.", + "CONFIRM_INTENT":"You want to rename room {{roomname}}, to {{newname}}, is that correct?", "ERROR": "Sorry, I couldn't rename this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't rename channel %s right now." }, "UNARCHIVE_CHANNEL": { "SUCCESS": "%s is now unarchived.", + "CONFIRM_INTENT":"You want to unarchive room {{roomname}}, is that correct?", "ERROR": "Sorry, I couldn't unarchive this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't unarchive channel %s right now." }, "CHANNEL_TOPIC": { "SUCCESS": "%s topic is now changed to %s", + "CONFIRM_INTENT": "You want to set topic of room, {{roomname}} as, {{topic}}, is that correct?", "ERROR": "Sorry, I couldn't change this channel topic right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't change topic for channel %s right now." }, "CHANNEL_DESCRIPTION": { "SUCCESS": "%s description is now changed to %s", + "CONFIRM_INTENT": "You want to set description of room, {{roomname}} as, {{description}}, is that correct?", "ERROR": "Sorry, I couldn't change this channel description right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't change description for channel %s right now." }, "CHANNEL_ANNOUNCEMENT": { "SUCCESS": "%s announcement is now changed to %s", + "CONFIRM_INTENT": "You want to set, %s, as announcement in room %s, is that correct?", + "NO_ROOM": "There is no room matching %s.", "ERROR": "Sorry, I couldn't change this channel announcement right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't change announcement for channel %s right now." }, "REMOVE_LEADER": { "SUCCESS": "%s is no longer the leader of %s.", + "CONFIRM_INTENT": "You want to remove {{username}}, as {{role}} of room {{channelname}}, is that correct?", "ERROR": "Sorry, I couldn't remove leader from this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't remove leader from channel %s right now." }, "REMOVE_MODERATOR": { "SUCCESS": "%s is no longer the moderator of %s.", + "CONFIRM_INTENT": "You want to remove {{username}}, as {{role}} of room {{channelname}}, is that correct?", "ERROR": "Sorry, I couldn't remove moderator from this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't remove moderator from channel %s right now." }, "REMOVE_OWNER": { "SUCCESS": "%s is no longer the owner of %s.", + "CONFIRM_INTENT": "You want to remove {{username}}, as {{role}} of room {{channelname}}, is that correct?", "ERROR": "Sorry, I couldn't remove owner from this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't remove owner from channel %s right now." - } + }, + "GET_ALL_UNREADS": { + "MESSAGE": "You have, {{message}}.", + "NO_UNREADS": "You don't have any unread messages.", + "ERROR": "Sorry, I am not able to get unread messages." + }, + "GET_ALL_UNREAD_MENTIONS": { + "MESSAGE": "You have, {{message}}.", + "NO_MENTIONS": "You don't have any unread mentions.", + "ERROR": "Sorry, I am not able to get your mentions." + }, + "GET_UNREAD_MESSAGES_FROM_DM": { + "NO_MESSAGE": "You don't have any unread messages from DM, {{name}}.", + "MESSAGE": "You have, {{unread}} unreads from {{name}}. {{responseString}}." + }, + "MENTIONS": { + "READ_MENTIONS": "You have {{count}} mentions in {{roomName}}. {{finalMessage}}.", + "NO_MENTIONS": "You don't have any mentions in {{roomName}}.", + "READ_DM_MENTIONS": "You have {{count}} mentions from {{name}}. {{finalMessage}}.", + "NO_DM_MENTIONS": "You don't have any mentions from DM, {{name}}.", + "ERROR": "Sorry, I couldn't get your mentions" + }, + "MESSAGE_TYPE": { + "TEXT_MESSAGE": "{{username}} says, {{message}}", + "CHANGE_DESCRIPTION": "{{username}} changed the description to, {{description}}.", + "CHANGE_ANNOUNCEMENT": "{{username}} made an announcement that says {{announcement}}.", + "CHANGE_TOPIC": "{{username}} changed the topic to {{topic}}.", + "IMAGE_MESSAGE": "{{username}} shared an image titled {{title}}.", + "VIDEO_MESSAGE": "{{username}} shared a video titled {{title}}.", + "FILE_MESSAGE": "{{username}} shared a file titled {{title}}.", + "DISCUSSION_CREATED": "{{username}} created a discussion named {{name}}.", + "UNKNOWN_MESSAGE": "{{username}}, performed some action" + }, + "HINTS": { + "GET_UNREADS": "Do I have any unread messages?", + "GET_UNREAD_MENTIONS": "Do I have any unread mentions?", + "READ_UNREADS_FROM_DISCUSSION": "Read unreads from a discussion", + "CHANGE_STATUS": "Change my status.", + "READ_MENTIONS_FROM_USER": "Read mentions from a user", + "LIST_DISCUSSIONS": "List my discussions", + "READ_UNREADS": "Read unreads messages from a channel.", + "CHANNEL_ANNOUNCEMENT": "Make an announcement.", + "POST_DIRECT_MESSAGE": "Send a direct message.", + "POST_DISCUSSION_MESSAGE": "Send message to a discussion." + }, + "STATUS": { + "SUCCESS": "I have changed your status.", + "ERROR": "Sorry, I could not change your status." + }, + "NO_ACTIVE_USER": "Couldn't find an active user named {{username}} from your contacts.", + "NO_ACTIVE_DISCUSSION": "Couldn't find an active discussion named {{name}} from your discussions.", + "NO_ACTIVE_ROOM": "Couldn't detect a room named {{name}}, maybe it's not active since long.", + "NO_ROOM": "You are not part of any channel or group named %s .", + "NO_ACTIVE_SUBSCRIPTION": "Couldn't detect a room or user named {{name}} from your subscriptions list. Maybe it's not active.", + "GENERIC_REPROMPT": "Anything else I can help you with?", + "SOMETHING_WENT_WRONG": "Sorry, something went wrong.", + "NO_USER": "There's no user named, %s in your contacts list.", + "NO_USER_WITH_ROLE": "There is no {{role}} named {{username}} in room {{channelname}}.", + "HINTS_TRANSITION": "You can try saying, ", + "TRY_AGAIN": "Sorry, something went wrong, can you please try again?", + "GENERIC_DENIED_MESSAGE": "Okay, Anything else I can help you with?" } \ No newline at end of file diff --git a/functions/locales/en-GB.json b/functions/locales/en-GB.json index 2630e24..c4f2a35 100644 --- a/functions/locales/en-GB.json +++ b/functions/locales/en-GB.json @@ -12,10 +12,16 @@ }, "WELCOME": { "SUCCESS": "Welcome To Rocket Chat Google Action. What Would you like to do today?", - "ERROR": "To start using this action, please link your account to authenticate." + "ERROR": "To start using this action, please link your account to authenticate.", + "AUTH_ERROR": "Sorry, I could not connect you with your account." }, "POST_MESSAGE": { "SUCCESS": "I've sent your message.", + "CONFIRM_DISCUSSION_INTENT": "You want to send, %s, to discussion %s. Is that correct?", + "CONFIRMATION": "You want to send, %s, to room %s, is that correct?", + "NO_CHANNEL": "There is no room named %s in your subscriptions list.", + "CONFIRM_DM_INTENT": "You want to send, %s, to user, %s, is that correct?", + "NO_USER": "There is no user named %s in your contacts list.", "ERROR": "Sorry, I couldn't send your message right now." }, "CREATE_CHANNEL": { @@ -27,6 +33,7 @@ }, "DELETE_CHANNEL": { "SUCCESS": "I've deleted the channel %s.", + "CONFIRM_INTENT": "You want to delete room {{roomname}}, is that correct?", "ERROR": "Sorry, I couldn't delete the channel %s right now.", "ERROR_NOT_FOUND": "Sorry, the channel %s does not exist. Please try again with different channel name." }, @@ -39,6 +46,7 @@ }, "MAKE_MODERATOR": { "SUCCESS": "%s is now the moderator of %s.", + "CONFIRM_INTENT": "You want to make %s, as moderator of room %s, is that correct?", "ERROR": "Sorry, I couldn't assign a moderator right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't assign a moderator to %s right now." }, @@ -49,17 +57,19 @@ }, "ADD_OWNER": { "SUCCESS": "%s is now the owner of %s.", + "CONFIRM_INTENT": "You want to make %s, as an owner of room %s, is that correct?", "ERROR": "Sorry, I couldn't assign a owner to the channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't assign a owner to channel %s right now." }, "ARCHIVE_CHANNEL": { "SUCCESS": "%s is now archived.", + "CONFIRM_INTENT": "You want to archive room {{roomname}}, is that correct?", "ERROR": "Sorry, I couldn't archive this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't archive channel %s right now." }, "GET_UNREAD_MESSAGES_FROM_CHANNEL": { - "NO_MESSAGE": "You have no unread messages.", - "MESSAGE": " You Have %s Unread Messages

%s

", + "NO_MESSAGE": "You don't have any unread messages in {{channelName}}.", + "MESSAGE": " You Have {{total}} unread activities and {{count}} Unread Messages in {{channelName}}.

{{responseString}}

", "ERROR": "Sorry, I couldn't get your unread messages right now.", "ERROR_NOT_FOUND": "Sorry, the channel %s does not exist. Please try again with different channel name." }, @@ -71,61 +81,134 @@ }, "INVITE_USER_TO_CHANNEL": { "SUCCESS": "%s is invited to the channel %s ", + "CONFIRM_INTENT": "You want to invite %s, to room %s, is that correct?", "ERROR": "Sorry I couldn't invite user %s to channel %s right now", "ERROR_NOT_FOUND": "Sorry, I couldn't find channel %s right now" }, - "LEAVE_CHANNEl": { + "LEAVE_CHANNEL": { "SUCCESS": "You Left channel %s .", + "CONFIRM_INTENT": "You want to leave room {{roomname}}, is that correct?", "ERROR": "Sorry, You couldn't leave the channel %s right now. Maybe you are the only owner of Channel so first set someone as the channel owner" }, "KICK_USER_FROM_CHANNEL": { "SUCCESS": "%s is now kicked from channel %s ", + "CONFIRM_INTENT": "You want to kick %s, from room %s, is that correct?", "ERROR": "Sorry I couldn't kick user %s from channel %s right now", "ERROR_NOT_FOUND": "Sorry, I couldn't find channel %s right now" }, "ADD_LEADER": { "SUCCESS": "%s is now the leader of %s.", + "CONFIRM_INTENT": "You want to make %s, as leader of room %s, is that correct?", "ERROR": "Sorry, I couldn't assign a leader to the channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't assign a leader to channel %s right now." }, "RENAME_ROOM": { "SUCCESS": "%s is now renamed to %s.", + "CONFIRM_INTENT":"You want to rename room {{roomname}}, to {{newname}}, is that correct?", "ERROR": "Sorry, I couldn't rename this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't rename channel %s right now." }, "UNARCHIVE_CHANNEL": { "SUCCESS": "%s is now unarchived.", + "CONFIRM_INTENT":"You want to unarchive room {{roomname}}, is that correct?", "ERROR": "Sorry, I couldn't unarchive this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't unarchive channel %s right now." }, "CHANNEL_TOPIC": { "SUCCESS": "%s topic is now changed to %s", + "CONFIRM_INTENT": "You want to set topic of room, {{roomname}} as, {{topic}}, is that correct?", "ERROR": "Sorry, I couldn't change this channel topic right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't change topic for channel %s right now." }, "CHANNEL_DESCRIPTION": { "SUCCESS": "%s description is now changed to %s", + "CONFIRM_INTENT": "You want to set description of room, {{roomname}} as, {{description}}, is that correct?", "ERROR": "Sorry, I couldn't change this channel description right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't change description for channel %s right now." }, "CHANNEL_ANNOUNCEMENT": { "SUCCESS": "%s announcement is now changed to %s", + "CONFIRM_INTENT": "You want to set, %s, as announcement in room %s, is that correct?", + "NO_ROOM": "There is no room matching %s.", "ERROR": "Sorry, I couldn't change this channel announcement right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't change announcement for channel %s right now." }, "REMOVE_LEADER": { "SUCCESS": "%s is no longer the leader of %s.", + "CONFIRM_INTENT": "You want to remove {{username}}, as {{role}} of room {{channelname}}, is that correct?", "ERROR": "Sorry, I couldn't remove leader from this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't remove leader from channel %s right now." }, "REMOVE_MODERATOR": { "SUCCESS": "%s is no longer the moderator of %s.", + "CONFIRM_INTENT": "You want to remove {{username}}, as {{role}} of room {{channelname}}, is that correct?", "ERROR": "Sorry, I couldn't remove moderator from this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't remove moderator from channel %s right now." }, "REMOVE_OWNER": { "SUCCESS": "%s is no longer the owner of %s.", + "CONFIRM_INTENT": "You want to remove {{username}}, as {{role}} of room {{channelname}}, is that correct?", "ERROR": "Sorry, I couldn't remove owner from this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't remove owner from channel %s right now." - } + }, + "GET_ALL_UNREADS": { + "MESSAGE": "You have, {{message}}.", + "NO_UNREADS": "You don't have any unread messages.", + "ERROR": "Sorry, I am not able to get unread messages." + }, + "GET_ALL_UNREAD_MENTIONS": { + "MESSAGE": "You have, {{message}}.", + "NO_MENTIONS": "You don't have any unread mentions.", + "ERROR": "Sorry, I am not able to get your mentions." + }, + "GET_UNREAD_MESSAGES_FROM_DM": { + "NO_MESSAGE": "You don't have any unread messages from DM, {{name}}.", + "MESSAGE": "You have, {{unread}} unreads from {{name}}. {{responseString}}." + }, + "MENTIONS": { + "READ_MENTIONS": "You have {{count}} mentions in {{roomName}}. {{finalMessage}}.", + "NO_MENTIONS": "You don't have any mentions in {{roomName}}.", + "READ_DM_MENTIONS": "You have {{count}} mentions from {{name}}. {{finalMessage}}.", + "NO_DM_MENTIONS": "You don't have any mentions from DM, {{name}}.", + "ERROR": "Sorry, I couldn't get your mentions" + }, + "MESSAGE_TYPE": { + "TEXT_MESSAGE": "{{username}} says, {{message}}", + "CHANGE_DESCRIPTION": "{{username}} changed the description to, {{description}}.", + "CHANGE_ANNOUNCEMENT": "{{username}} made an announcement that says {{announcement}}.", + "CHANGE_TOPIC": "{{username}} changed the topic to {{topic}}.", + "IMAGE_MESSAGE": "{{username}} shared an image titled {{title}}.", + "VIDEO_MESSAGE": "{{username}} shared a video titled {{title}}.", + "FILE_MESSAGE": "{{username}} shared a file titled {{title}}.", + "DISCUSSION_CREATED": "{{username}} created a discussion named {{name}}.", + "UNKNOWN_MESSAGE": "{{username}}, performed some action" + }, + "HINTS": { + "GET_UNREADS": "Do I have any unread messages?", + "GET_UNREAD_MENTIONS": "Do I have any unread mentions?", + "READ_UNREADS_FROM_DISCUSSION": "Read unreads from a discussion", + "CHANGE_STATUS": "Change my status.", + "READ_MENTIONS_FROM_USER": "Read mentions from a user", + "LIST_DISCUSSIONS": "List my discussions", + "READ_UNREADS": "Read unreads messages from a channel.", + "CHANNEL_ANNOUNCEMENT": "Make an announcement.", + "POST_DIRECT_MESSAGE": "Send a direct message.", + "POST_DISCUSSION_MESSAGE": "Send message to a discussion." + }, + "STATUS": { + "SUCCESS": "I have changed your status.", + "ERROR": "Sorry, I could not change your status." + }, + "NO_ACTIVE_USER": "Couldn't find an active user named {{username}} from your contacts.", + "NO_ACTIVE_DISCUSSION": "Couldn't find an active discussion named {{name}} from your discussions.", + "NO_ACTIVE_ROOM": "Couldn't detect a room named {{name}}, maybe it's not active since long.", + "NO_ROOM": "You are not part of any channel or group named %s .", + "NO_ACTIVE_SUBSCRIPTION": "Couldn't detect a room or user named {{name}} from your subscriptions list. Maybe it's not active.", + "GENERIC_REPROMPT": "Anything else I can help you with?", + "SOMETHING_WENT_WRONG": "Sorry, something went wrong.", + "NO_USER": "There's no user named, %s in your contacts list.", + "NO_USER_WITH_ROLE": "There is no {{role}} named {{username}} in room {{channelname}}.", + "HINTS_TRANSITION": "You can try saying, ", + "TRY_AGAIN": "Sorry, something went wrong, can you please try again?", + "GENERIC_DENIED_MESSAGE": "Okay, Anything else I can help you with?" } \ No newline at end of file diff --git a/functions/locales/en-IN.json b/functions/locales/en-IN.json index 2630e24..c4f2a35 100644 --- a/functions/locales/en-IN.json +++ b/functions/locales/en-IN.json @@ -12,10 +12,16 @@ }, "WELCOME": { "SUCCESS": "Welcome To Rocket Chat Google Action. What Would you like to do today?", - "ERROR": "To start using this action, please link your account to authenticate." + "ERROR": "To start using this action, please link your account to authenticate.", + "AUTH_ERROR": "Sorry, I could not connect you with your account." }, "POST_MESSAGE": { "SUCCESS": "I've sent your message.", + "CONFIRM_DISCUSSION_INTENT": "You want to send, %s, to discussion %s. Is that correct?", + "CONFIRMATION": "You want to send, %s, to room %s, is that correct?", + "NO_CHANNEL": "There is no room named %s in your subscriptions list.", + "CONFIRM_DM_INTENT": "You want to send, %s, to user, %s, is that correct?", + "NO_USER": "There is no user named %s in your contacts list.", "ERROR": "Sorry, I couldn't send your message right now." }, "CREATE_CHANNEL": { @@ -27,6 +33,7 @@ }, "DELETE_CHANNEL": { "SUCCESS": "I've deleted the channel %s.", + "CONFIRM_INTENT": "You want to delete room {{roomname}}, is that correct?", "ERROR": "Sorry, I couldn't delete the channel %s right now.", "ERROR_NOT_FOUND": "Sorry, the channel %s does not exist. Please try again with different channel name." }, @@ -39,6 +46,7 @@ }, "MAKE_MODERATOR": { "SUCCESS": "%s is now the moderator of %s.", + "CONFIRM_INTENT": "You want to make %s, as moderator of room %s, is that correct?", "ERROR": "Sorry, I couldn't assign a moderator right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't assign a moderator to %s right now." }, @@ -49,17 +57,19 @@ }, "ADD_OWNER": { "SUCCESS": "%s is now the owner of %s.", + "CONFIRM_INTENT": "You want to make %s, as an owner of room %s, is that correct?", "ERROR": "Sorry, I couldn't assign a owner to the channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't assign a owner to channel %s right now." }, "ARCHIVE_CHANNEL": { "SUCCESS": "%s is now archived.", + "CONFIRM_INTENT": "You want to archive room {{roomname}}, is that correct?", "ERROR": "Sorry, I couldn't archive this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't archive channel %s right now." }, "GET_UNREAD_MESSAGES_FROM_CHANNEL": { - "NO_MESSAGE": "You have no unread messages.", - "MESSAGE": " You Have %s Unread Messages

%s

", + "NO_MESSAGE": "You don't have any unread messages in {{channelName}}.", + "MESSAGE": " You Have {{total}} unread activities and {{count}} Unread Messages in {{channelName}}.

{{responseString}}

", "ERROR": "Sorry, I couldn't get your unread messages right now.", "ERROR_NOT_FOUND": "Sorry, the channel %s does not exist. Please try again with different channel name." }, @@ -71,61 +81,134 @@ }, "INVITE_USER_TO_CHANNEL": { "SUCCESS": "%s is invited to the channel %s ", + "CONFIRM_INTENT": "You want to invite %s, to room %s, is that correct?", "ERROR": "Sorry I couldn't invite user %s to channel %s right now", "ERROR_NOT_FOUND": "Sorry, I couldn't find channel %s right now" }, - "LEAVE_CHANNEl": { + "LEAVE_CHANNEL": { "SUCCESS": "You Left channel %s .", + "CONFIRM_INTENT": "You want to leave room {{roomname}}, is that correct?", "ERROR": "Sorry, You couldn't leave the channel %s right now. Maybe you are the only owner of Channel so first set someone as the channel owner" }, "KICK_USER_FROM_CHANNEL": { "SUCCESS": "%s is now kicked from channel %s ", + "CONFIRM_INTENT": "You want to kick %s, from room %s, is that correct?", "ERROR": "Sorry I couldn't kick user %s from channel %s right now", "ERROR_NOT_FOUND": "Sorry, I couldn't find channel %s right now" }, "ADD_LEADER": { "SUCCESS": "%s is now the leader of %s.", + "CONFIRM_INTENT": "You want to make %s, as leader of room %s, is that correct?", "ERROR": "Sorry, I couldn't assign a leader to the channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't assign a leader to channel %s right now." }, "RENAME_ROOM": { "SUCCESS": "%s is now renamed to %s.", + "CONFIRM_INTENT":"You want to rename room {{roomname}}, to {{newname}}, is that correct?", "ERROR": "Sorry, I couldn't rename this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't rename channel %s right now." }, "UNARCHIVE_CHANNEL": { "SUCCESS": "%s is now unarchived.", + "CONFIRM_INTENT":"You want to unarchive room {{roomname}}, is that correct?", "ERROR": "Sorry, I couldn't unarchive this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't unarchive channel %s right now." }, "CHANNEL_TOPIC": { "SUCCESS": "%s topic is now changed to %s", + "CONFIRM_INTENT": "You want to set topic of room, {{roomname}} as, {{topic}}, is that correct?", "ERROR": "Sorry, I couldn't change this channel topic right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't change topic for channel %s right now." }, "CHANNEL_DESCRIPTION": { "SUCCESS": "%s description is now changed to %s", + "CONFIRM_INTENT": "You want to set description of room, {{roomname}} as, {{description}}, is that correct?", "ERROR": "Sorry, I couldn't change this channel description right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't change description for channel %s right now." }, "CHANNEL_ANNOUNCEMENT": { "SUCCESS": "%s announcement is now changed to %s", + "CONFIRM_INTENT": "You want to set, %s, as announcement in room %s, is that correct?", + "NO_ROOM": "There is no room matching %s.", "ERROR": "Sorry, I couldn't change this channel announcement right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't change announcement for channel %s right now." }, "REMOVE_LEADER": { "SUCCESS": "%s is no longer the leader of %s.", + "CONFIRM_INTENT": "You want to remove {{username}}, as {{role}} of room {{channelname}}, is that correct?", "ERROR": "Sorry, I couldn't remove leader from this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't remove leader from channel %s right now." }, "REMOVE_MODERATOR": { "SUCCESS": "%s is no longer the moderator of %s.", + "CONFIRM_INTENT": "You want to remove {{username}}, as {{role}} of room {{channelname}}, is that correct?", "ERROR": "Sorry, I couldn't remove moderator from this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't remove moderator from channel %s right now." }, "REMOVE_OWNER": { "SUCCESS": "%s is no longer the owner of %s.", + "CONFIRM_INTENT": "You want to remove {{username}}, as {{role}} of room {{channelname}}, is that correct?", "ERROR": "Sorry, I couldn't remove owner from this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't remove owner from channel %s right now." - } + }, + "GET_ALL_UNREADS": { + "MESSAGE": "You have, {{message}}.", + "NO_UNREADS": "You don't have any unread messages.", + "ERROR": "Sorry, I am not able to get unread messages." + }, + "GET_ALL_UNREAD_MENTIONS": { + "MESSAGE": "You have, {{message}}.", + "NO_MENTIONS": "You don't have any unread mentions.", + "ERROR": "Sorry, I am not able to get your mentions." + }, + "GET_UNREAD_MESSAGES_FROM_DM": { + "NO_MESSAGE": "You don't have any unread messages from DM, {{name}}.", + "MESSAGE": "You have, {{unread}} unreads from {{name}}. {{responseString}}." + }, + "MENTIONS": { + "READ_MENTIONS": "You have {{count}} mentions in {{roomName}}. {{finalMessage}}.", + "NO_MENTIONS": "You don't have any mentions in {{roomName}}.", + "READ_DM_MENTIONS": "You have {{count}} mentions from {{name}}. {{finalMessage}}.", + "NO_DM_MENTIONS": "You don't have any mentions from DM, {{name}}.", + "ERROR": "Sorry, I couldn't get your mentions" + }, + "MESSAGE_TYPE": { + "TEXT_MESSAGE": "{{username}} says, {{message}}", + "CHANGE_DESCRIPTION": "{{username}} changed the description to, {{description}}.", + "CHANGE_ANNOUNCEMENT": "{{username}} made an announcement that says {{announcement}}.", + "CHANGE_TOPIC": "{{username}} changed the topic to {{topic}}.", + "IMAGE_MESSAGE": "{{username}} shared an image titled {{title}}.", + "VIDEO_MESSAGE": "{{username}} shared a video titled {{title}}.", + "FILE_MESSAGE": "{{username}} shared a file titled {{title}}.", + "DISCUSSION_CREATED": "{{username}} created a discussion named {{name}}.", + "UNKNOWN_MESSAGE": "{{username}}, performed some action" + }, + "HINTS": { + "GET_UNREADS": "Do I have any unread messages?", + "GET_UNREAD_MENTIONS": "Do I have any unread mentions?", + "READ_UNREADS_FROM_DISCUSSION": "Read unreads from a discussion", + "CHANGE_STATUS": "Change my status.", + "READ_MENTIONS_FROM_USER": "Read mentions from a user", + "LIST_DISCUSSIONS": "List my discussions", + "READ_UNREADS": "Read unreads messages from a channel.", + "CHANNEL_ANNOUNCEMENT": "Make an announcement.", + "POST_DIRECT_MESSAGE": "Send a direct message.", + "POST_DISCUSSION_MESSAGE": "Send message to a discussion." + }, + "STATUS": { + "SUCCESS": "I have changed your status.", + "ERROR": "Sorry, I could not change your status." + }, + "NO_ACTIVE_USER": "Couldn't find an active user named {{username}} from your contacts.", + "NO_ACTIVE_DISCUSSION": "Couldn't find an active discussion named {{name}} from your discussions.", + "NO_ACTIVE_ROOM": "Couldn't detect a room named {{name}}, maybe it's not active since long.", + "NO_ROOM": "You are not part of any channel or group named %s .", + "NO_ACTIVE_SUBSCRIPTION": "Couldn't detect a room or user named {{name}} from your subscriptions list. Maybe it's not active.", + "GENERIC_REPROMPT": "Anything else I can help you with?", + "SOMETHING_WENT_WRONG": "Sorry, something went wrong.", + "NO_USER": "There's no user named, %s in your contacts list.", + "NO_USER_WITH_ROLE": "There is no {{role}} named {{username}} in room {{channelname}}.", + "HINTS_TRANSITION": "You can try saying, ", + "TRY_AGAIN": "Sorry, something went wrong, can you please try again?", + "GENERIC_DENIED_MESSAGE": "Okay, Anything else I can help you with?" } \ No newline at end of file diff --git a/functions/locales/en-US.json b/functions/locales/en-US.json index 2630e24..c4f2a35 100644 --- a/functions/locales/en-US.json +++ b/functions/locales/en-US.json @@ -12,10 +12,16 @@ }, "WELCOME": { "SUCCESS": "Welcome To Rocket Chat Google Action. What Would you like to do today?", - "ERROR": "To start using this action, please link your account to authenticate." + "ERROR": "To start using this action, please link your account to authenticate.", + "AUTH_ERROR": "Sorry, I could not connect you with your account." }, "POST_MESSAGE": { "SUCCESS": "I've sent your message.", + "CONFIRM_DISCUSSION_INTENT": "You want to send, %s, to discussion %s. Is that correct?", + "CONFIRMATION": "You want to send, %s, to room %s, is that correct?", + "NO_CHANNEL": "There is no room named %s in your subscriptions list.", + "CONFIRM_DM_INTENT": "You want to send, %s, to user, %s, is that correct?", + "NO_USER": "There is no user named %s in your contacts list.", "ERROR": "Sorry, I couldn't send your message right now." }, "CREATE_CHANNEL": { @@ -27,6 +33,7 @@ }, "DELETE_CHANNEL": { "SUCCESS": "I've deleted the channel %s.", + "CONFIRM_INTENT": "You want to delete room {{roomname}}, is that correct?", "ERROR": "Sorry, I couldn't delete the channel %s right now.", "ERROR_NOT_FOUND": "Sorry, the channel %s does not exist. Please try again with different channel name." }, @@ -39,6 +46,7 @@ }, "MAKE_MODERATOR": { "SUCCESS": "%s is now the moderator of %s.", + "CONFIRM_INTENT": "You want to make %s, as moderator of room %s, is that correct?", "ERROR": "Sorry, I couldn't assign a moderator right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't assign a moderator to %s right now." }, @@ -49,17 +57,19 @@ }, "ADD_OWNER": { "SUCCESS": "%s is now the owner of %s.", + "CONFIRM_INTENT": "You want to make %s, as an owner of room %s, is that correct?", "ERROR": "Sorry, I couldn't assign a owner to the channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't assign a owner to channel %s right now." }, "ARCHIVE_CHANNEL": { "SUCCESS": "%s is now archived.", + "CONFIRM_INTENT": "You want to archive room {{roomname}}, is that correct?", "ERROR": "Sorry, I couldn't archive this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't archive channel %s right now." }, "GET_UNREAD_MESSAGES_FROM_CHANNEL": { - "NO_MESSAGE": "You have no unread messages.", - "MESSAGE": " You Have %s Unread Messages

%s

", + "NO_MESSAGE": "You don't have any unread messages in {{channelName}}.", + "MESSAGE": " You Have {{total}} unread activities and {{count}} Unread Messages in {{channelName}}.

{{responseString}}

", "ERROR": "Sorry, I couldn't get your unread messages right now.", "ERROR_NOT_FOUND": "Sorry, the channel %s does not exist. Please try again with different channel name." }, @@ -71,61 +81,134 @@ }, "INVITE_USER_TO_CHANNEL": { "SUCCESS": "%s is invited to the channel %s ", + "CONFIRM_INTENT": "You want to invite %s, to room %s, is that correct?", "ERROR": "Sorry I couldn't invite user %s to channel %s right now", "ERROR_NOT_FOUND": "Sorry, I couldn't find channel %s right now" }, - "LEAVE_CHANNEl": { + "LEAVE_CHANNEL": { "SUCCESS": "You Left channel %s .", + "CONFIRM_INTENT": "You want to leave room {{roomname}}, is that correct?", "ERROR": "Sorry, You couldn't leave the channel %s right now. Maybe you are the only owner of Channel so first set someone as the channel owner" }, "KICK_USER_FROM_CHANNEL": { "SUCCESS": "%s is now kicked from channel %s ", + "CONFIRM_INTENT": "You want to kick %s, from room %s, is that correct?", "ERROR": "Sorry I couldn't kick user %s from channel %s right now", "ERROR_NOT_FOUND": "Sorry, I couldn't find channel %s right now" }, "ADD_LEADER": { "SUCCESS": "%s is now the leader of %s.", + "CONFIRM_INTENT": "You want to make %s, as leader of room %s, is that correct?", "ERROR": "Sorry, I couldn't assign a leader to the channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't assign a leader to channel %s right now." }, "RENAME_ROOM": { "SUCCESS": "%s is now renamed to %s.", + "CONFIRM_INTENT":"You want to rename room {{roomname}}, to {{newname}}, is that correct?", "ERROR": "Sorry, I couldn't rename this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't rename channel %s right now." }, "UNARCHIVE_CHANNEL": { "SUCCESS": "%s is now unarchived.", + "CONFIRM_INTENT":"You want to unarchive room {{roomname}}, is that correct?", "ERROR": "Sorry, I couldn't unarchive this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't unarchive channel %s right now." }, "CHANNEL_TOPIC": { "SUCCESS": "%s topic is now changed to %s", + "CONFIRM_INTENT": "You want to set topic of room, {{roomname}} as, {{topic}}, is that correct?", "ERROR": "Sorry, I couldn't change this channel topic right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't change topic for channel %s right now." }, "CHANNEL_DESCRIPTION": { "SUCCESS": "%s description is now changed to %s", + "CONFIRM_INTENT": "You want to set description of room, {{roomname}} as, {{description}}, is that correct?", "ERROR": "Sorry, I couldn't change this channel description right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't change description for channel %s right now." }, "CHANNEL_ANNOUNCEMENT": { "SUCCESS": "%s announcement is now changed to %s", + "CONFIRM_INTENT": "You want to set, %s, as announcement in room %s, is that correct?", + "NO_ROOM": "There is no room matching %s.", "ERROR": "Sorry, I couldn't change this channel announcement right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't change announcement for channel %s right now." }, "REMOVE_LEADER": { "SUCCESS": "%s is no longer the leader of %s.", + "CONFIRM_INTENT": "You want to remove {{username}}, as {{role}} of room {{channelname}}, is that correct?", "ERROR": "Sorry, I couldn't remove leader from this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't remove leader from channel %s right now." }, "REMOVE_MODERATOR": { "SUCCESS": "%s is no longer the moderator of %s.", + "CONFIRM_INTENT": "You want to remove {{username}}, as {{role}} of room {{channelname}}, is that correct?", "ERROR": "Sorry, I couldn't remove moderator from this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't remove moderator from channel %s right now." }, "REMOVE_OWNER": { "SUCCESS": "%s is no longer the owner of %s.", + "CONFIRM_INTENT": "You want to remove {{username}}, as {{role}} of room {{channelname}}, is that correct?", "ERROR": "Sorry, I couldn't remove owner from this channel right now.", "ERROR_NOT_FOUND": "Sorry, I couldn't remove owner from channel %s right now." - } + }, + "GET_ALL_UNREADS": { + "MESSAGE": "You have, {{message}}.", + "NO_UNREADS": "You don't have any unread messages.", + "ERROR": "Sorry, I am not able to get unread messages." + }, + "GET_ALL_UNREAD_MENTIONS": { + "MESSAGE": "You have, {{message}}.", + "NO_MENTIONS": "You don't have any unread mentions.", + "ERROR": "Sorry, I am not able to get your mentions." + }, + "GET_UNREAD_MESSAGES_FROM_DM": { + "NO_MESSAGE": "You don't have any unread messages from DM, {{name}}.", + "MESSAGE": "You have, {{unread}} unreads from {{name}}. {{responseString}}." + }, + "MENTIONS": { + "READ_MENTIONS": "You have {{count}} mentions in {{roomName}}. {{finalMessage}}.", + "NO_MENTIONS": "You don't have any mentions in {{roomName}}.", + "READ_DM_MENTIONS": "You have {{count}} mentions from {{name}}. {{finalMessage}}.", + "NO_DM_MENTIONS": "You don't have any mentions from DM, {{name}}.", + "ERROR": "Sorry, I couldn't get your mentions" + }, + "MESSAGE_TYPE": { + "TEXT_MESSAGE": "{{username}} says, {{message}}", + "CHANGE_DESCRIPTION": "{{username}} changed the description to, {{description}}.", + "CHANGE_ANNOUNCEMENT": "{{username}} made an announcement that says {{announcement}}.", + "CHANGE_TOPIC": "{{username}} changed the topic to {{topic}}.", + "IMAGE_MESSAGE": "{{username}} shared an image titled {{title}}.", + "VIDEO_MESSAGE": "{{username}} shared a video titled {{title}}.", + "FILE_MESSAGE": "{{username}} shared a file titled {{title}}.", + "DISCUSSION_CREATED": "{{username}} created a discussion named {{name}}.", + "UNKNOWN_MESSAGE": "{{username}}, performed some action" + }, + "HINTS": { + "GET_UNREADS": "Do I have any unread messages?", + "GET_UNREAD_MENTIONS": "Do I have any unread mentions?", + "READ_UNREADS_FROM_DISCUSSION": "Read unreads from a discussion", + "CHANGE_STATUS": "Change my status.", + "READ_MENTIONS_FROM_USER": "Read mentions from a user", + "LIST_DISCUSSIONS": "List my discussions", + "READ_UNREADS": "Read unreads messages from a channel.", + "CHANNEL_ANNOUNCEMENT": "Make an announcement.", + "POST_DIRECT_MESSAGE": "Send a direct message.", + "POST_DISCUSSION_MESSAGE": "Send message to a discussion." + }, + "STATUS": { + "SUCCESS": "I have changed your status.", + "ERROR": "Sorry, I could not change your status." + }, + "NO_ACTIVE_USER": "Couldn't find an active user named {{username}} from your contacts.", + "NO_ACTIVE_DISCUSSION": "Couldn't find an active discussion named {{name}} from your discussions.", + "NO_ACTIVE_ROOM": "Couldn't detect a room named {{name}}, maybe it's not active since long.", + "NO_ROOM": "You are not part of any channel or group named %s .", + "NO_ACTIVE_SUBSCRIPTION": "Couldn't detect a room or user named {{name}} from your subscriptions list. Maybe it's not active.", + "GENERIC_REPROMPT": "Anything else I can help you with?", + "SOMETHING_WENT_WRONG": "Sorry, something went wrong.", + "NO_USER": "There's no user named, %s in your contacts list.", + "NO_USER_WITH_ROLE": "There is no {{role}} named {{username}} in room {{channelname}}.", + "HINTS_TRANSITION": "You can try saying, ", + "TRY_AGAIN": "Sorry, something went wrong, can you please try again?", + "GENERIC_DENIED_MESSAGE": "Okay, Anything else I can help you with?" } \ No newline at end of file diff --git a/functions/locales/hi-IN.json b/functions/locales/hi-IN.json index 1c5e116..5d19bbe 100644 --- a/functions/locales/hi-IN.json +++ b/functions/locales/hi-IN.json @@ -16,6 +16,10 @@ }, "POST_MESSAGE": { "SUCCESS": "मैंने आपका संदेश भेज दिया है।", + "CONFIRMATION": "आप भेजना चाहते हैं, %s . चैनल %s में . क्या ये सही है", + "NO_CHANNEL": "%s नाम का कोई चैनल नहीं है .", + "CONFIRM_DM_INTENT": "आप भेजना चाहते हैं, %s, उपयोगकर्ता %s को, क्या ये सही है?", + "NO_USER": "आपकी संपर्क सूची में %s नाम का कोई उपयोगकर्ता नहीं है।", "ERROR": "क्षमा करें, मैं अभी आपका संदेश नहीं भेज सका।" }, "CREATE_CHANNEL": { @@ -109,6 +113,8 @@ }, "CHANNEL_ANNOUNCEMENT": { "SUCCESS": "%s की घोषणा अब %s में बदल दिया गया है", + "CONFIRM_INTENT": "आप, %s को, %s, में घोषणा के रूप में सेट करना चाहते हैं, क्या ये सही है?", + "NO_ROOM": "%s नाम का कोई चैनल नहीं है", "ERROR": "क्षमा करें, मैं इस चैनल की घोषणा को अभी नहीं बदल सका।", "ERROR_NOT_FOUND": "क्षमा करें, मैं अभी चैनल %s के लिए घोषणा नहीं बदल सका।" }, diff --git a/functions/package-lock.json b/functions/package-lock.json index 3257b28..ffd1569 100644 --- a/functions/package-lock.json +++ b/functions/package-lock.json @@ -1156,6 +1156,12 @@ "is-obj": "^1.0.0" } }, + "dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==", + "dev": true + }, "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", @@ -2893,9 +2899,9 @@ "optional": true }, "ipaddr.js": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", - "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, "is-buffer": { "version": "2.0.3", @@ -3522,12 +3528,12 @@ } }, "proxy-addr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", - "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", "requires": { "forwarded": "~0.1.2", - "ipaddr.js": "1.9.0" + "ipaddr.js": "1.9.1" } }, "pseudomap": { @@ -3872,6 +3878,11 @@ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" }, + "string-similarity": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/string-similarity/-/string-similarity-4.0.1.tgz", + "integrity": "sha512-v36MJzloekKVvKAsYi6O/qpn2mIuvwEFIT9Gx3yg4spkNjXYsk7yxc37g4ZTyMVIBvt/9PZGxnqEtme8XHK+Mw==" + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", diff --git a/functions/package.json b/functions/package.json index 6adccaa..c82f446 100644 --- a/functions/package.json +++ b/functions/package.json @@ -10,7 +10,8 @@ }, "scripts": { "start": "firebase serve --only functions", - "deploy": "firebase deploy --only functions" + "deploy": "firebase deploy --only functions", + "local": "DEVELOPMENT=true node index.js" }, "dependencies": { "@vitalets/google-translate-api": "^2.8.0", @@ -22,6 +23,11 @@ "i18n": "^0.8.3", "moji-translate": "^1.0.8", "moment": "^2.18.1", - "remove-whitespace": "^1.1.0" + "remove-whitespace": "^1.1.0", + "string-similarity": "^4.0.1" + }, + "devDependencies": { + "dotenv": "^8.2.0", + "express": "^4.17.1" } }