diff --git a/client/package.json b/client/package.json index 772b9ab11..291097304 100644 --- a/client/package.json +++ b/client/package.json @@ -43,10 +43,8 @@ "redux-persist": "^6.0.0", "redux-saga": "^1.1.3", "reselect": "^4.0.0", - "styled-components": "^5.0.1", - "subscriptions-transport-ws": "^0.9.16", - "twilio": "^3.41.1" + "subscriptions-transport-ws": "^0.9.16" }, "scripts": { "analyze": "source-map-explorer 'build/static/js/*.js'", diff --git a/client/src/components/chat-conversation/chat-conversation.closed.component.jsx b/client/src/components/chat-conversation/chat-conversation.closed.component.jsx new file mode 100644 index 000000000..298bd41ca --- /dev/null +++ b/client/src/components/chat-conversation/chat-conversation.closed.component.jsx @@ -0,0 +1,37 @@ +import { Button } from "antd"; +import React from "react"; +import { connect } from "react-redux"; +import { closeConversation, sendMessage, toggleConversationVisible } from "../../redux/messaging/messaging.actions"; +import PhoneFormatter from "../../utils/PhoneFormatter"; + +const mapDispatchToProps = dispatch => ({ + toggleConversationVisible: conversationId => + dispatch(toggleConversationVisible(conversationId)), + closeConversation: phone => dispatch(closeConversation(phone)), + sendMessage: message => dispatch(sendMessage(message)) +}); + +function ChatConversationClosedComponent({ + conversation, + toggleConversationVisible, + closeConversation +}) { + return ( +
+
toggleConversationVisible(conversation.phone)}> + {conversation.phone} +
+ +
+ ); +} + +export default connect( + null, + mapDispatchToProps +)(ChatConversationClosedComponent); diff --git a/client/src/components/chat-conversation/chat-conversation.component.jsx b/client/src/components/chat-conversation/chat-conversation.component.jsx index c2e0c3073..59dcb66b1 100644 --- a/client/src/components/chat-conversation/chat-conversation.component.jsx +++ b/client/src/components/chat-conversation/chat-conversation.component.jsx @@ -1,22 +1,16 @@ -import { Button, Card, Input } from "antd"; -import Icon from '@ant-design/icons'; -import React, { useEffect, useState } from "react"; +import { Button, Card } from "antd"; +import React from "react"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; -import twilio from "twilio"; import { closeConversation, + sendMessage, toggleConversationVisible } from "../../redux/messaging/messaging.actions"; import PhoneFormatter from "../../utils/PhoneFormatter"; +import ChatConversationOpenComponent from "./chat-conversation.open.component"; import "./chat-conversation.styles.scss"; //https://bootsnipp.com/snippets/exR5v -import { MdSend } from "react-icons/md"; -import { useTranslation } from "react-i18next"; - -const client = twilio( - "ACf1b1aaf0e04740828b49b6e58467d787", - "0bea5e29a6d77593183ab1caa01d23de" -); +import ChatConversationClosedComponent from "./chat-conversation.closed.component"; const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser @@ -24,35 +18,17 @@ const mapStateToProps = createStructuredSelector({ const mapDispatchToProps = dispatch => ({ toggleConversationVisible: conversationId => dispatch(toggleConversationVisible(conversationId)), - closeConversation: phone => dispatch(closeConversation(phone)) + closeConversation: phone => dispatch(closeConversation(phone)), + sendMessage: message => dispatch(sendMessage(message)) }); -export default connect( - mapStateToProps, - mapDispatchToProps -)(function ChatConversationComponent({ + +export function ChatConversationComponent({ conversation, toggleConversationVisible, closeConversation }) { - const { t } = useTranslation(); + const messages = []; - const [messages, setMessages] = useState([]); - - useEffect(() => { - client.messages.list({ limit: 20 }, (error, items) => { - setMessages( - items.reduce((acc, value) => { - acc.push({ - sid: value.sid, - direction: value.direction, - body: value.body - }); - return acc; - }, []) - ); - }); - return () => {}; - }, [setMessages]); return (
toggleConversationVisible(conversation.phone)} - > + onClick={() => toggleConversationVisible(conversation.phone)}> {conversation.phone}
@@ -78,44 +52,18 @@ export default connect( width: conversation.open ? "400px" : "175px", margin: "0px 10px" }} - size="small" - > + size='small'> {conversation.open ? ( -
-
- -
- } - /> -
+ ) : ( -
-
toggleConversationVisible(conversation.phone)}> - {conversation.phone} -
- -
+ )} ); -}); +} + +export default connect( + mapStateToProps, + mapDispatchToProps +)(ChatConversationComponent); diff --git a/client/src/components/chat-conversation/chat-conversation.open.component.jsx b/client/src/components/chat-conversation/chat-conversation.open.component.jsx new file mode 100644 index 000000000..1d99de63f --- /dev/null +++ b/client/src/components/chat-conversation/chat-conversation.open.component.jsx @@ -0,0 +1,27 @@ +import React from "react"; +import ChatSendMessage from "../chat-send-message/chat-send-message.component"; +export default function ChatConversationOpenComponent({ + conversation, + messages +}) { + if (!!!messages) return
No Messages
; + + return ( +
+
+
    + {messages.map(item => ( +
  • +

    {item.body}

    +
  • + ))} +
+
+ +
+ ); +} diff --git a/client/src/components/chat-send-message/chat-send-message.component.jsx b/client/src/components/chat-send-message/chat-send-message.component.jsx new file mode 100644 index 000000000..1fcd9db32 --- /dev/null +++ b/client/src/components/chat-send-message/chat-send-message.component.jsx @@ -0,0 +1,48 @@ +import { Input } from "antd"; +import React, { useState } from "react"; +import { useTranslation } from "react-i18next"; +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { sendMessage } from "../../redux/messaging/messaging.actions"; +import { selectBodyshop } from "../../redux/user/user.selectors"; + +const mapStateToProps = createStructuredSelector({ + bodyshop: selectBodyshop +}); +const mapDispatchToProps = dispatch => ({ + sendMessage: message => dispatch(sendMessage(message)) +}); + +function ChatSendMessageComponent({ conversation, bodyshop, sendMessage }) { + const [message, setMessage] = useState(""); + const { t } = useTranslation(); + console.log("message", message); + + const handleEnter = () => { + console.log("Sending that message "); + sendMessage({ + to: conversation.phone, + body: message, + messagingServiceSid: bodyshop.messagingservicesid + }); + }; + + return ( +
+ setMessage(e.target.value)} + onPressEnter={event => { + if (!!!event.shiftKey) handleEnter(); + }} + /> +
+ ); +} +export default connect( + mapStateToProps, + mapDispatchToProps +)(ChatSendMessageComponent); diff --git a/client/src/graphql/bodyshop.queries.js b/client/src/graphql/bodyshop.queries.js index c345e2e0e..67e65a422 100644 --- a/client/src/graphql/bodyshop.queries.js +++ b/client/src/graphql/bodyshop.queries.js @@ -22,6 +22,7 @@ export const QUERY_BODYSHOP = gql` zip_post region_config md_responsibility_centers + messagingservicesid employees { id first_name diff --git a/client/src/pages/manage/manage.page.container.jsx b/client/src/pages/manage/manage.page.container.jsx index 5ad4641eb..13b2caba6 100644 --- a/client/src/pages/manage/manage.page.container.jsx +++ b/client/src/pages/manage/manage.page.container.jsx @@ -5,20 +5,24 @@ import AlertComponent from "../../components/alert/alert.component"; import { QUERY_BODYSHOP } from "../../graphql/bodyshop.queries"; import { setBodyshop } from "../../redux/user/user.actions"; import ManagePage from "./manage.page.component"; +import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component"; +import { useTranslation } from "react-i18next"; const mapDispatchToProps = dispatch => ({ setBodyshop: bs => dispatch(setBodyshop(bs)) }); function ManagePageContainer({ match, setBodyshop }) { - const { error, data } = useQuery(QUERY_BODYSHOP, { + const { loading, error, data } = useQuery(QUERY_BODYSHOP, { fetchPolicy: "network-only" }); - + const { t } = useTranslation(); useEffect(() => { if (data) setBodyshop(data.bodyshops[0]); }, [data, setBodyshop]); + if (loading) + return ; if (error) return ; return ; } diff --git a/client/src/redux/messaging/messaging.actions.js b/client/src/redux/messaging/messaging.actions.js index b89ab0ebb..dc8f2bc0e 100644 --- a/client/src/redux/messaging/messaging.actions.js +++ b/client/src/redux/messaging/messaging.actions.js @@ -19,3 +19,13 @@ export const closeConversation = phone => ({ type: MessagingActionTypes.CLOSE_CONVERSATION, payload: phone }); + +export const sendMessage = message => ({ + type: MessagingActionTypes.SEND_MESSAGE, + payload: message +}); + +export const sendMessageFailure = error => ({ + type: MessagingActionTypes.SEND_MESSAGE_FAILURE, + payload: error +}); diff --git a/client/src/redux/messaging/messaging.reducer.js b/client/src/redux/messaging/messaging.reducer.js index f9acdf08e..200875dec 100644 --- a/client/src/redux/messaging/messaging.reducer.js +++ b/client/src/redux/messaging/messaging.reducer.js @@ -3,8 +3,16 @@ import MessagingActionTypes from "./messaging.types"; const INITIAL_STATE = { visible: false, conversations: [ - { phone: "6049992002", open: false }, - { phone: "6049992991", open: false } + { + phone: "6049992002", + id: "519ba10d-6467-4fa5-9c22-59ae891edeb6", + open: false + }, + { + phone: "6049992991", + id: "ab57deba-eeb9-40db-b5ae-23f3ce8d7c7b", + open: false + } ] }; diff --git a/client/src/redux/messaging/messaging.sagas.js b/client/src/redux/messaging/messaging.sagas.js index e9ffa9a1a..a911a6406 100644 --- a/client/src/redux/messaging/messaging.sagas.js +++ b/client/src/redux/messaging/messaging.sagas.js @@ -1,5 +1,23 @@ -import { all } from "redux-saga/effects"; +import { all, call, put, takeLatest } from "redux-saga/effects"; +import { sendMessageFailure } from "./messaging.actions"; +import MessagingActionTypes from "./messaging.types"; +import axios from "axios"; + +export function* onSendMessage() { + yield takeLatest(MessagingActionTypes.SEND_MESSAGE, sendMessage); +} +export function* sendMessage(payload) { + try { + console.log("Message Contents", payload); + axios.post("/sms/send", payload).then(response => { + console.log(JSON.stringify(response)); + }); + } catch (error) { + console.log("Error in sendMessage saga."); + yield put(sendMessageFailure(error)); + } +} export function* messagingSagas() { - yield all([]); + yield all([call(onSendMessage)]); } diff --git a/client/src/redux/messaging/messaging.types.js b/client/src/redux/messaging/messaging.types.js index 462e7efb3..83d0403b1 100644 --- a/client/src/redux/messaging/messaging.types.js +++ b/client/src/redux/messaging/messaging.types.js @@ -4,6 +4,7 @@ const MessagingActionTypes = { OPEN_CONVERSATION: "OPEN_CONVERSATION", CLOSE_CONVERSATION: "CLOSE_CONVERSATION", TOGGLE_CONVERSATION_VISIBLE: "TOGGLE_CONVERSATION_VISIBLE", - SEND_MESSAGE: "SEND_MESSAGE" + SEND_MESSAGE: "SEND_MESSAGE", + SEND_MESSAGE_FAILURE: "SEND_MESSAGE_FAILURE" }; export default MessagingActionTypes; diff --git a/client/yarn.lock b/client/yarn.lock index 16a468c07..f2651106a 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -2145,14 +2145,6 @@ dependencies: "@babel/types" "^7.3.0" -"@types/body-parser@*": - version "1.19.0" - resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f" - integrity sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ== - dependencies: - "@types/connect" "*" - "@types/node" "*" - "@types/bytebuffer@^5.0.40": version "5.0.40" resolved "https://registry.yarnpkg.com/@types/bytebuffer/-/bytebuffer-5.0.40.tgz#d6faac40dcfb09cd856cdc4c01d3690ba536d3ee" @@ -2166,13 +2158,6 @@ resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== -"@types/connect@*": - version "3.4.33" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.33.tgz#31610c901eca573b8713c3330abc6e6b9f588546" - integrity sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A== - dependencies: - "@types/node" "*" - "@types/eslint-visitor-keys@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" @@ -2183,23 +2168,6 @@ resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== -"@types/express-serve-static-core@*": - version "4.17.2" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.2.tgz#f6f41fa35d42e79dbf6610eccbb2637e6008a0cf" - integrity sha512-El9yMpctM6tORDAiBwZVLMcxoTMcqqRO9dVyYcn7ycLWbvR8klrDn8CAOwRfZujZtWD7yS/mshTdz43jMOejbg== - dependencies: - "@types/node" "*" - "@types/range-parser" "*" - -"@types/express@^4.17.3": - version "4.17.3" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.3.tgz#38e4458ce2067873b09a73908df488870c303bd9" - integrity sha512-I8cGRJj3pyOLs/HndoP+25vOqhqWkAZsWMEmq1qXy/b/M3ppufecUwaK2/TVDVxcV61/iSdhykUjQQ2DLSrTdg== - dependencies: - "@types/body-parser" "*" - "@types/express-serve-static-core" "*" - "@types/serve-static" "*" - "@types/glob@^7.1.1": version "7.1.1" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575" @@ -2244,11 +2212,6 @@ resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9" integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w== -"@types/mime@*": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d" - integrity sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw== - "@types/minimatch@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" @@ -2279,11 +2242,6 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== -"@types/range-parser@*": - version "1.2.3" - resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c" - integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA== - "@types/react@^16.9.11": version "16.9.23" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.23.tgz#1a66c6d468ba11a8943ad958a8cb3e737568271c" @@ -2292,14 +2250,6 @@ "@types/prop-types" "*" csstype "^2.2.0" -"@types/serve-static@*": - version "1.13.3" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.3.tgz#eb7e1c41c4468272557e897e9171ded5e2ded9d1" - integrity sha512-oprSwp094zOglVrXdlo/4bAHtKTAxX6VT8FOZlBKrmyLbNvE1zxZyJ6yikMVtHIvwP45+ZQGJn+FdXGKTozq0g== - dependencies: - "@types/express-serve-static-core" "*" - "@types/mime" "*" - "@types/stack-utils@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" @@ -3055,7 +3005,7 @@ arrify@^1.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= -asap@^2.0.0, asap@^2.0.3, asap@~2.0.3, asap@~2.0.6: +asap@^2.0.3, asap@~2.0.3, asap@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= @@ -3621,11 +3571,6 @@ btoa@^1.2.1: resolved "https://registry.yarnpkg.com/btoa/-/btoa-1.2.1.tgz#01a9909f8b2c93f6bf680ba26131eb30f7fa3d73" integrity sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g== -buffer-equal-constant-time@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" - integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= - buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -4796,11 +4741,6 @@ date-arithmetic@^4.0.1: resolved "https://registry.yarnpkg.com/date-arithmetic/-/date-arithmetic-4.1.0.tgz#e5d6434e9deb71f79760a37b729e4a515e730ddf" integrity sha512-QWxYLR5P/6GStZcdem+V1xoto6DMadYWpMXU82ES3/RfR3Wdwr3D0+be7mgOJ+Ov0G9D5Dmb9T17sNLQYj9XOg== -dayjs@^1.8.21: - version "1.8.23" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.8.23.tgz#07b5a8e759c4d75ae07bdd0ad6977f851c01e510" - integrity sha512-NmYHMFONftoZbeOhVz6jfiXI4zSiPN6NoVWJgC0aZQfYVwzy/ZpESPHuCcI0B8BUMpSJQ08zenHDbofOLKq8hQ== - debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -5177,13 +5117,6 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -ecdsa-sig-formatter@1.0.11: - version "1.0.11" - resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" - integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== - dependencies: - safe-buffer "^5.0.1" - ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -8046,22 +7979,6 @@ jsonify@~0.0.0: resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= -jsonwebtoken@^8.5.1: - version "8.5.1" - resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" - integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== - dependencies: - jws "^3.2.2" - lodash.includes "^4.3.0" - lodash.isboolean "^3.0.3" - lodash.isinteger "^4.0.4" - lodash.isnumber "^3.0.3" - lodash.isplainobject "^4.0.6" - lodash.isstring "^4.0.1" - lodash.once "^4.0.0" - ms "^2.1.1" - semver "^5.6.0" - jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" @@ -8080,23 +7997,6 @@ jsx-ast-utils@^2.2.1, jsx-ast-utils@^2.2.3: array-includes "^3.0.3" object.assign "^4.1.0" -jwa@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" - integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== - dependencies: - buffer-equal-constant-time "1.0.1" - ecdsa-sig-formatter "1.0.11" - safe-buffer "^5.0.1" - -jws@^3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" - integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== - dependencies: - jwa "^1.4.1" - safe-buffer "^5.0.1" - killable@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" @@ -8320,47 +8220,22 @@ lodash.get@^4.4.2: resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= -lodash.includes@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" - integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8= - -lodash.isboolean@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" - integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY= - lodash.isequal@^4.0.0, lodash.isequal@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= -lodash.isinteger@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" - integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M= - -lodash.isnumber@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" - integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w= - lodash.isplainobject@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs= -lodash.isstring@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" - integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= - lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= -lodash.once@^4.0.0, lodash.once@^4.1.1: +lodash.once@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= @@ -9852,11 +9727,6 @@ pnp-webpack-plugin@1.6.4: dependencies: ts-pnp "^1.1.6" -pop-iterate@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/pop-iterate/-/pop-iterate-1.0.1.tgz#ceacfdab4abf353d7a0f2aaa2c1fc7b3f9413ba3" - integrity sha1-zqz9q0q/NT16DyqqLB/Hs/lBO6M= - popper.js@^1.15.0: version "1.16.1" resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" @@ -10744,15 +10614,6 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -q@2.0.x: - version "2.0.3" - resolved "https://registry.yarnpkg.com/q/-/q-2.0.3.tgz#75b8db0255a1a5af82f58c3f3aaa1efec7d0d134" - integrity sha1-dbjbAlWhpa+C9Yw/Oqoe/sfQ0TQ= - dependencies: - asap "^2.0.0" - pop-iterate "^1.0.1" - weak-map "^1.0.5" - q@^1.1.2: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" @@ -10763,11 +10624,6 @@ qs@6.7.0: resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== -qs@^6.9.1: - version "6.9.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.2.tgz#a27b695006544a04bf0e6c6a7e8120778926d5bd" - integrity sha512-2eQ6zajpK7HwqrY1rRtGw5IZvjgtELXzJECaEDuzDFo2jjnIXpJSimzd4qflWZq6bLLi+Zgfj5eDrAzl/lptyg== - qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" @@ -12116,11 +11972,6 @@ rmc-feedback@^2.0.0: babel-runtime "6.x" classnames "^2.2.5" -rootpath@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/rootpath/-/rootpath-0.1.2.tgz#5b379a87dca906e9b91d690a599439bef267ea6b" - integrity sha1-Wzeah9ypBum5HWkKWZQ5vvJn6ms= - rst-selector-parser@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz#81b230ea2fcc6066c89e3472de794285d9b03d91" @@ -12284,11 +12135,6 @@ schema-utils@^2.6.5: ajv "^6.12.0" ajv-keywords "^3.4.1" -scmp@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/scmp/-/scmp-2.1.0.tgz#37b8e197c425bdeb570ab91cc356b311a11f9c9a" - integrity sha512-o/mRQGk9Rcer/jEEw/yw4mwo3EU/NvYvp577/Btqrym9Qy5/MdWGBqipbALgd2lrdWTJ5/gqDusxfnQBxOxT2Q== - screenfull@^5.0.0: version "5.0.2" resolved "https://registry.yarnpkg.com/screenfull/-/screenfull-5.0.2.tgz#b9acdcf1ec676a948674df5cd0ff66b902b0bed7" @@ -13449,23 +13295,6 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= -twilio@^3.41.1: - version "3.41.1" - resolved "https://registry.yarnpkg.com/twilio/-/twilio-3.41.1.tgz#653f2daccad7fe3ac0362acd1a1347e690dd9795" - integrity sha512-YOAuQtb3xELQJDcL+G6ffDRrZeJSlFRph5peudFYcEa9Or5R0x+r8lShXlYl7yP8w7atCWxETSeySLuStEpvhg== - dependencies: - "@types/express" "^4.17.3" - axios "^0.19.2" - dayjs "^1.8.21" - jsonwebtoken "^8.5.1" - lodash "^4.17.15" - q "2.0.x" - qs "^6.9.1" - rootpath "^0.1.2" - scmp "^2.1.0" - url-parse "^1.4.7" - xmlbuilder "^13.0.2" - type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" @@ -13646,7 +13475,7 @@ url-loader@2.3.0: mime "^2.4.4" schema-utils "^2.5.0" -url-parse@^1.4.3, url-parse@^1.4.7: +url-parse@^1.4.3: version "1.4.7" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278" integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg== @@ -13812,11 +13641,6 @@ wbuf@^1.1.0, wbuf@^1.7.3: dependencies: minimalistic-assert "^1.0.0" -weak-map@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/weak-map/-/weak-map-1.0.5.tgz#79691584d98607f5070bd3b70a40e6bb22e401eb" - integrity sha1-eWkVhNmGB/UHC9O3CkDmuyLkAes= - webidl-conversions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" @@ -14245,11 +14069,6 @@ xml-name-validator@^3.0.0: resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== -xmlbuilder@^13.0.2: - version "13.0.2" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-13.0.2.tgz#02ae33614b6a047d1c32b5389c1fdacb2bce47a7" - integrity sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ== - xmlchars@^2.1.1: version "2.2.0" resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" diff --git a/hasura/migrations/1585160133244_alter_table_public_messages_add_column_isoutbound/down.yaml b/hasura/migrations/1585160133244_alter_table_public_messages_add_column_isoutbound/down.yaml new file mode 100644 index 000000000..8d67ac880 --- /dev/null +++ b/hasura/migrations/1585160133244_alter_table_public_messages_add_column_isoutbound/down.yaml @@ -0,0 +1,5 @@ +- args: + cascade: false + read_only: false + sql: ALTER TABLE "public"."messages" DROP COLUMN "isoutbound"; + type: run_sql diff --git a/hasura/migrations/1585160133244_alter_table_public_messages_add_column_isoutbound/up.yaml b/hasura/migrations/1585160133244_alter_table_public_messages_add_column_isoutbound/up.yaml new file mode 100644 index 000000000..c1f7bb533 --- /dev/null +++ b/hasura/migrations/1585160133244_alter_table_public_messages_add_column_isoutbound/up.yaml @@ -0,0 +1,6 @@ +- args: + cascade: false + read_only: false + sql: ALTER TABLE "public"."messages" ADD COLUMN "isoutbound" boolean NOT NULL + DEFAULT false; + type: run_sql diff --git a/hasura/migrations/1585160140032_update_permission_user_public_table_messages/down.yaml b/hasura/migrations/1585160140032_update_permission_user_public_table_messages/down.yaml new file mode 100644 index 000000000..c3f1ece2c --- /dev/null +++ b/hasura/migrations/1585160140032_update_permission_user_public_table_messages/down.yaml @@ -0,0 +1,38 @@ +- args: + role: user + table: + name: messages + schema: public + type: drop_insert_permission +- args: + permission: + check: + conversation: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + columns: + - id + - created_at + - updated_at + - msid + - conversationid + - text + - image + - image_path + - sent + - delivered + localPresets: + - key: "" + value: "" + set: {} + role: user + table: + name: messages + schema: public + type: create_insert_permission diff --git a/hasura/migrations/1585160140032_update_permission_user_public_table_messages/up.yaml b/hasura/migrations/1585160140032_update_permission_user_public_table_messages/up.yaml new file mode 100644 index 000000000..3d5f212d0 --- /dev/null +++ b/hasura/migrations/1585160140032_update_permission_user_public_table_messages/up.yaml @@ -0,0 +1,39 @@ +- args: + role: user + table: + name: messages + schema: public + type: drop_insert_permission +- args: + permission: + check: + conversation: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + columns: + - id + - created_at + - updated_at + - msid + - conversationid + - text + - image + - image_path + - sent + - delivered + - isoutbound + localPresets: + - key: "" + value: "" + set: {} + role: user + table: + name: messages + schema: public + type: create_insert_permission diff --git a/hasura/migrations/1585160145919_update_permission_user_public_table_messages/down.yaml b/hasura/migrations/1585160145919_update_permission_user_public_table_messages/down.yaml new file mode 100644 index 000000000..829390ace --- /dev/null +++ b/hasura/migrations/1585160145919_update_permission_user_public_table_messages/down.yaml @@ -0,0 +1,36 @@ +- args: + role: user + table: + name: messages + schema: public + type: drop_select_permission +- args: + permission: + allow_aggregations: false + columns: + - delivered + - image + - sent + - image_path + - msid + - text + - created_at + - updated_at + - conversationid + - id + computed_fields: [] + filter: + conversation: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + role: user + table: + name: messages + schema: public + type: create_select_permission diff --git a/hasura/migrations/1585160145919_update_permission_user_public_table_messages/up.yaml b/hasura/migrations/1585160145919_update_permission_user_public_table_messages/up.yaml new file mode 100644 index 000000000..24e4f5a60 --- /dev/null +++ b/hasura/migrations/1585160145919_update_permission_user_public_table_messages/up.yaml @@ -0,0 +1,37 @@ +- args: + role: user + table: + name: messages + schema: public + type: drop_select_permission +- args: + permission: + allow_aggregations: false + columns: + - delivered + - image + - isoutbound + - sent + - image_path + - msid + - text + - created_at + - updated_at + - conversationid + - id + computed_fields: [] + filter: + conversation: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + role: user + table: + name: messages + schema: public + type: create_select_permission diff --git a/hasura/migrations/1585160150937_update_permission_user_public_table_messages/down.yaml b/hasura/migrations/1585160150937_update_permission_user_public_table_messages/down.yaml new file mode 100644 index 000000000..31797c48f --- /dev/null +++ b/hasura/migrations/1585160150937_update_permission_user_public_table_messages/down.yaml @@ -0,0 +1,38 @@ +- args: + role: user + table: + name: messages + schema: public + type: drop_update_permission +- args: + permission: + columns: + - delivered + - image + - sent + - image_path + - msid + - text + - created_at + - updated_at + - conversationid + - id + filter: + conversation: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + localPresets: + - key: "" + value: "" + set: {} + role: user + table: + name: messages + schema: public + type: create_update_permission diff --git a/hasura/migrations/1585160150937_update_permission_user_public_table_messages/up.yaml b/hasura/migrations/1585160150937_update_permission_user_public_table_messages/up.yaml new file mode 100644 index 000000000..29938a450 --- /dev/null +++ b/hasura/migrations/1585160150937_update_permission_user_public_table_messages/up.yaml @@ -0,0 +1,39 @@ +- args: + role: user + table: + name: messages + schema: public + type: drop_update_permission +- args: + permission: + columns: + - delivered + - image + - isoutbound + - sent + - image_path + - msid + - text + - created_at + - updated_at + - conversationid + - id + filter: + conversation: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + localPresets: + - key: "" + value: "" + set: {} + role: user + table: + name: messages + schema: public + type: create_update_permission diff --git a/hasura/migrations/1585160687805_alter_table_public_bodyshops_add_column_messagingservicesid/down.yaml b/hasura/migrations/1585160687805_alter_table_public_bodyshops_add_column_messagingservicesid/down.yaml new file mode 100644 index 000000000..588c83295 --- /dev/null +++ b/hasura/migrations/1585160687805_alter_table_public_bodyshops_add_column_messagingservicesid/down.yaml @@ -0,0 +1,5 @@ +- args: + cascade: false + read_only: false + sql: ALTER TABLE "public"."bodyshops" DROP COLUMN "messagingservicesid"; + type: run_sql diff --git a/hasura/migrations/1585160687805_alter_table_public_bodyshops_add_column_messagingservicesid/up.yaml b/hasura/migrations/1585160687805_alter_table_public_bodyshops_add_column_messagingservicesid/up.yaml new file mode 100644 index 000000000..a6cfbbc1d --- /dev/null +++ b/hasura/migrations/1585160687805_alter_table_public_bodyshops_add_column_messagingservicesid/up.yaml @@ -0,0 +1,6 @@ +- args: + cascade: false + read_only: false + sql: ALTER TABLE "public"."bodyshops" ADD COLUMN "messagingservicesid" text NULL + UNIQUE; + type: run_sql diff --git a/hasura/migrations/1585176085942_update_permission_user_public_table_bodyshops/down.yaml b/hasura/migrations/1585176085942_update_permission_user_public_table_bodyshops/down.yaml new file mode 100644 index 000000000..c3ec5c35a --- /dev/null +++ b/hasura/migrations/1585176085942_update_permission_user_public_table_bodyshops/down.yaml @@ -0,0 +1,42 @@ +- args: + role: user + table: + name: bodyshops + schema: public + type: drop_select_permission +- args: + permission: + allow_aggregations: false + columns: + - id + - shopname + - created_at + - updated_at + - address1 + - address2 + - city + - state + - zip_post + - country + - email + - federal_tax_id + - insurance_vendor_id + - state_tax_id + - logo_img_path + - md_ro_statuses + - region_config + - md_order_statuses + - md_responsibility_centers + computed_fields: [] + filter: + associations: + bodyshop: + associations: + user: + authid: + _eq: X-Hasura-User-Id + role: user + table: + name: bodyshops + schema: public + type: create_select_permission diff --git a/hasura/migrations/1585176085942_update_permission_user_public_table_bodyshops/up.yaml b/hasura/migrations/1585176085942_update_permission_user_public_table_bodyshops/up.yaml new file mode 100644 index 000000000..825ae0c0c --- /dev/null +++ b/hasura/migrations/1585176085942_update_permission_user_public_table_bodyshops/up.yaml @@ -0,0 +1,43 @@ +- args: + role: user + table: + name: bodyshops + schema: public + type: drop_select_permission +- args: + permission: + allow_aggregations: false + columns: + - id + - shopname + - created_at + - updated_at + - address1 + - address2 + - city + - state + - zip_post + - country + - email + - federal_tax_id + - insurance_vendor_id + - state_tax_id + - logo_img_path + - md_ro_statuses + - region_config + - md_order_statuses + - md_responsibility_centers + - messagingservicesid + computed_fields: [] + filter: + associations: + bodyshop: + associations: + user: + authid: + _eq: X-Hasura-User-Id + role: user + table: + name: bodyshops + schema: public + type: create_select_permission diff --git a/package.json b/package.json index 707a8e633..6c64a81ec 100644 --- a/package.json +++ b/package.json @@ -25,8 +25,11 @@ "express": "^4.16.4", "express-sslify": "^1.2.0", "firebase-tools": "^7.14.0", + "graphql-request": "^1.8.2", "nodemailer": "^6.4.4", - "source-map-explorer": "^2.3.1" + "phone": "^2.4.8", + "source-map-explorer": "^2.3.1", + "twilio": "^3.41.1" }, "devDependencies": { "concurrently": "^5.1.0", diff --git a/server.js b/server.js index 85225ef77..b4fb77a3a 100644 --- a/server.js +++ b/server.js @@ -3,6 +3,7 @@ const cors = require("cors"); const bodyParser = require("body-parser"); const path = require("path"); const compression = require("compression"); +const twilio = require("twilio"); var enforce = require("express-sslify"); if (process.env.NODE_ENV !== "production") require("dotenv").config(); @@ -25,9 +26,21 @@ app.post("/delete_s3", s3upload.delete_s3); var sendEmail = require("./sendemail.js"); app.post("/sendemail", sendEmail.sendEmail); -// app.get("/test", function(req, res) { -// res.json({ success: true }); -// }); + +app.get("/test", function(req, res) { + res.json({ success: true }); +}); + +var smsReceive = require("./server/sms/receive"); +app.post( + "/sms/receive", + twilio.webhook({ validate: process.env.NODE_ENV === "PRODUCTION" }), + smsReceive.receive +); +var smsSend = require("./server/sms/send"); +app.post("/sms/send", smsSend.send); +var smsStatus = require("./server/sms/status"); +app.post("/sms/status", smsStatus.status); var downloadImages = require("./download-images"); app.get("/downloadImages", downloadImages.downloadImages); diff --git a/server/graphql-client/graphql-client.js b/server/graphql-client/graphql-client.js new file mode 100644 index 000000000..2307187e7 --- /dev/null +++ b/server/graphql-client/graphql-client.js @@ -0,0 +1,9 @@ +const GraphQLClient = require("graphql-request").GraphQLClient; +require("dotenv").config(); + +//TODO May need to use a different client that includes caching of resources. +exports.client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, { + headers: { + "x-hasura-admin-secret": process.env.HASURA_ADMIN_SECRET + } +}); diff --git a/server/graphql-client/queries.js b/server/graphql-client/queries.js new file mode 100644 index 000000000..e3a4c7a66 --- /dev/null +++ b/server/graphql-client/queries.js @@ -0,0 +1,23 @@ +exports.FIND_BODYSHOP_BY_MESSAGING_SERVICE_SID = ` +query FIND_BODYSHOP_BY_MESSAGING_SERVICE_SID( + $mssid: String! + $phone: String! + ) { + bodyshops(where: { messagingservicesid: { _eq: $mssid } }) { + id + conversations(where: { phone_num: { _eq: $phone } }) { + id + } + } + } +`; + +exports.INSERT_MESSAGE = ` +mutation INSERT_MESSAGE($msg: [messages_insert_input!]!) { + insert_messages(objects: $msg) { + returning { + id + } + } + } + `; diff --git a/server/sms/receive.js b/server/sms/receive.js new file mode 100644 index 000000000..c73f2d881 --- /dev/null +++ b/server/sms/receive.js @@ -0,0 +1,82 @@ +require("dotenv").config(); +const client = require("../graphql-client/graphql-client").client; +const queries = require("../graphql-client/queries"); +const phone = require("phone"); + +exports.receive = (req, res) => { + //Perform request validation + if (!req.body || !req.body.MessagingServiceSid || !req.body.SmsMessageSid) { + res.sendStatus(400); + } else { + client + .request(queries.FIND_BODYSHOP_BY_MESSAGING_SERVICE_SID, { + mssid: req.body.MessagingServiceSid, + phone: phone(req.body.From)[0] + }) + .then(response => { + //TODO Add logic for handling MMS. + let newMessage = { msid: req.body.SmsMessageSid, text: req.body.Body }; + if (response.bodyshops[0]) { + //Found a bodyshop - should always happen. + if (response.bodyshops[0].conversations.length === 0) { + //No conversation Found, create one. + console.log("[SMS Receive] No conversation found. Creating one."); + newMessage.conversation = { + data: { + bodyshopid: response.bodyshops[0].id, + phone_num: phone(req.body.From)[0] + } + }; + } else if (response.bodyshops[0].conversations.length === 1) { + //Just add it to the conversation + console.log("[SMS Receive] Conversation found. Added ID."); + newMessage.conversationid = + response.bodyshops[0].conversations[0].id; + } else { + //We should never get here. + console.log( + "Massive Error: Duplicate Phone Numbers for MSSID: " + + req.body.MessagingServiceSid + ); + } + + client + .request(queries.INSERT_MESSAGE, { msg: newMessage }) + .then(r2 => { + res.sendStatus(200); + }) + .catch(e2 => { + console.log("e2", e2); + res.json(e2); + }); + } + }) + .catch(e1 => { + console.log("e1", e1); + res.json(e1); + }); + } +}; + +// const sampleMessage: { +// "ToCountry": "CA", +// "ToState": "BC", +// "SmsMessageSid": "SMad7bddaf3454c0904999d6018b1e8f49", +// "NumMedia": "0", +// "ToCity": "Vancouver", +// "FromZip": "", +// "SmsSid": "SMad7bddaf3454c0904999d6018b1e8f49", +// "FromState": "BC", +// "SmsStatus": "received", +// "FromCity": "VANCOUVER", +// "Body": "Hi", +// "FromCountry": "CA", +// "To": "+16043301606", +// "MessagingServiceSid": "MG6e259e2add04ffa0d0aa355038670ee1", +// "ToZip": "", +// "NumSegments": "1", +// "MessageSid": "SMad7bddaf3454c0904999d6018b1e8f49", +// "AccountSid": "AC6c09d337d6b9c68ab6488c2052bd457c", +// "From": "+16049992002", +// "ApiVersion": "2010-04-01" +// } diff --git a/server/sms/send.js b/server/sms/send.js new file mode 100644 index 000000000..01f909713 --- /dev/null +++ b/server/sms/send.js @@ -0,0 +1,41 @@ +require("dotenv").config(); +const twilio = require("twilio"); +const phone = require("phone"); + +const client = twilio( + process.env.TWILIO_AUTH_TOKEN, + process.env.TWILIO_AUTH_KEY +); + +exports.send = (req, res) => { + console.log("Sending an SMS!"); + const { to, messagingServiceSid, body, conversationid } = req.body; + + if (!!to && !!messagingServiceSid && !!body && !!conversationid) { + client.messages + .create({ + body: body, + messagingServiceSid: messagingServiceSid, + to: phone(to)[0] + }) + .then(message => { + let newMessage = { + msid: message.sid, + text: body, + conversationid, + isoutbound: true + }; + client + .request(queries.INSERT_MESSAGE, { msg: newMessage }) + .then(r2 => { + res.sendStatus(200); + }) + .catch(e2 => { + res.json({ success: false, message: e2 }); + }); + }) + .catch(error => res.json({ success: false, message: error })); + } else { + res.json({ success: false, message: "Missing required parameter(s)." }); + } +}; diff --git a/server/sms/status.js b/server/sms/status.js new file mode 100644 index 000000000..5cbc312ce --- /dev/null +++ b/server/sms/status.js @@ -0,0 +1,23 @@ +require("dotenv").config(); +const client = require("../graphql-client/graphql-client").client; +const queries = require("../graphql-client/queries"); +const phone = require("phone"); + +exports.status = (req, res) => { + //Perform request validation + console.log("Inbound Status Update: ", JSON.stringify(req.body)); + res.sendStatus(200); +}; + +// Inbound Sample +// { +// "SmsSid": "SM5205ea340e06437799d9345e7283457c", +// "SmsStatus": "queued", +// "MessageStatus": "queued", +// "To": "+16049992002", +// "MessagingServiceSid": "MG6e259e2add04ffa0d0aa355038670ee1", +// "MessageSid": "SM5205ea340e06437799d9345e7283457c", +// "AccountSid": "AC6c09d337d6b9c68ab6488c2052bd457c", +// "From": "+16043301606", +// "ApiVersion": "2010-04-01" +// } diff --git a/yarn.lock b/yarn.lock index 138f1a30d..22eec6e0d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -136,11 +136,26 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-1.2.0.tgz#63ce3638cb85231f3704164c90a18ef816da3fb7" integrity sha512-mwhXGkRV5dlvQc4EgPDxDxO6WuMBVymGFd1CA+2Y+z5dG9MNspoQ+AWjl/Ld1MnpCL8AKbosZlDVohqcIwuWsw== +"@types/body-parser@*": + version "1.19.0" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f" + integrity sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ== + dependencies: + "@types/connect" "*" + "@types/node" "*" + "@types/color-name@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== +"@types/connect@*": + version "3.4.33" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.33.tgz#31610c901eca573b8713c3330abc6e6b9f588546" + integrity sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A== + dependencies: + "@types/node" "*" + "@types/duplexify@^3.6.0": version "3.6.0" resolved "https://registry.yarnpkg.com/@types/duplexify/-/duplexify-3.6.0.tgz#dfc82b64bd3a2168f5bd26444af165bf0237dcd8" @@ -148,11 +163,33 @@ dependencies: "@types/node" "*" +"@types/express-serve-static-core@*": + version "4.17.3" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.3.tgz#dc8068ee3e354d7fba69feb86b3dfeee49b10f09" + integrity sha512-sHEsvEzjqN+zLbqP+8OXTipc10yH1QLR+hnr5uw29gi9AhCAAAdri8ClNV7iMdrJrIzXIQtlkPvq8tJGhj3QJQ== + dependencies: + "@types/node" "*" + "@types/range-parser" "*" + +"@types/express@^4.17.3": + version "4.17.3" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.3.tgz#38e4458ce2067873b09a73908df488870c303bd9" + integrity sha512-I8cGRJj3pyOLs/HndoP+25vOqhqWkAZsWMEmq1qXy/b/M3ppufecUwaK2/TVDVxcV61/iSdhykUjQQ2DLSrTdg== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "*" + "@types/serve-static" "*" + "@types/long@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.0.tgz#719551d2352d301ac8b81db732acb6bdc28dbdef" integrity sha512-1w52Nyx4Gq47uuu0EVcsHBxZFJgurQ+rTKS3qMHxR1GY2T8c2AJYd6vZoZ9q1rupaDjU0yT+Jc2XTyXkjeMA+Q== +"@types/mime@*": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d" + integrity sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw== + "@types/node@*": version "12.12.17" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.17.tgz#191b71e7f4c325ee0fb23bc4a996477d92b8c39b" @@ -163,6 +200,19 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.9.tgz#4f251a1ed77ac7ef09d456247d67fc8173f6b9da" integrity sha512-+6VygF9LbG7Gaqeog2G7u1+RUcmo0q1rI+2ZxdIg2fAUngk5Vz9fOCHXdloNUOHEPd1EuuOpL5O0CdgN9Fx5UQ== +"@types/range-parser@*": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c" + integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA== + +"@types/serve-static@*": + version "1.13.3" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.3.tgz#eb7e1c41c4468272557e897e9171ded5e2ded9d1" + integrity sha512-oprSwp094zOglVrXdlo/4bAHtKTAxX6VT8FOZlBKrmyLbNvE1zxZyJ6yikMVtHIvwP45+ZQGJn+FdXGKTozq0g== + dependencies: + "@types/express-serve-static-core" "*" + "@types/mime" "*" + JSONStream@^1.2.1: version "1.3.5" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" @@ -355,6 +405,11 @@ as-array@^2.0.0: resolved "https://registry.yarnpkg.com/as-array/-/as-array-2.0.0.tgz#4f04805d87f8fce8e511bc2108f8e5e3a287d547" integrity sha1-TwSAXYf4/OjlEbwhCPjl46KH1Uc= +asap@^2.0.0: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= + asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" @@ -440,6 +495,13 @@ axios@^0.19.0: follow-redirects "1.5.10" is-buffer "^2.0.2" +axios@^0.19.2: + version "0.19.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27" + integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA== + dependencies: + follow-redirects "1.5.10" + balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -993,6 +1055,14 @@ cross-env@^5.1.3: dependencies: cross-spawn "^6.0.5" +cross-fetch@2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-2.2.2.tgz#a47ff4f7fc712daba8f6a695a11c948440d45723" + integrity sha1-pH/09/xxLauo9qaVoRyUhEDUVyM= + dependencies: + node-fetch "2.1.2" + whatwg-fetch "2.0.4" + cross-spawn@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" @@ -1058,6 +1128,11 @@ date-fns@^2.0.1: resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.10.0.tgz#abd10604d8bafb0bcbd2ba2e9b0563b922ae4b6b" integrity sha512-EhfEKevYGWhWlZbNeplfhIU/+N+x0iCIx7VzKlXma2EdQyznVlZhCptXUY+BegNpPW2kjdx15Rvq503YcXXrcA== +dayjs@^1.8.21: + version "1.8.23" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.8.23.tgz#07b5a8e759c4d75ae07bdd0ad6977f851c01e510" + integrity sha512-NmYHMFONftoZbeOhVz6jfiXI4zSiPN6NoVWJgC0aZQfYVwzy/ZpESPHuCcI0B8BUMpSJQ08zenHDbofOLKq8hQ== + debug@2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -1971,6 +2046,13 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== +graphql-request@^1.8.2: + version "1.8.2" + resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-1.8.2.tgz#398d10ae15c585676741bde3fc01d5ca948f8fbe" + integrity sha512-dDX2M+VMsxXFCmUX0Vo0TopIZIX4ggzOtiCsThgtrKR4niiaagsGTDIHj3fsOMFETpa064vzovI+4YV4QnMbcg== + dependencies: + cross-fetch "2.2.2" + gtoken@^2.3.0: version "2.3.3" resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-2.3.3.tgz#8a7fe155c5ce0c4b71c886cfb282a9060d94a641" @@ -2459,7 +2541,7 @@ jsonschema@^1.0.2: resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.2.5.tgz#bab69d97fa28946aec0a56a9cc266d23fe80ae61" integrity sha512-kVTF+08x25PQ0CjuVc0gRM9EUPb0Fe9Ln/utFOgcdxEIOHuU7ooBk/UPTd7t1M91pP35m0MU1T8M5P7vP1bRRw== -jsonwebtoken@^8.2.1: +jsonwebtoken@^8.2.1, jsonwebtoken@^8.5.1: version "8.5.1" resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== @@ -2927,6 +3009,11 @@ node-emoji@^1.4.1: dependencies: lodash.toarray "^4.4.0" +node-fetch@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.1.2.tgz#ab884e8e7e57e38a944753cec706f788d1768bb5" + integrity sha1-q4hOjn5X44qUR1POxwb3iNF2i7U= + node-fetch@^2.3.0, node-fetch@^2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" @@ -3189,6 +3276,11 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= +phone@^2.4.8: + version "2.4.8" + resolved "https://registry.yarnpkg.com/phone/-/phone-2.4.8.tgz#4da4c046b4a90ca65ea04f86e99094b50ed518df" + integrity sha512-8RO0PfJPzjsWKhbU9W79f7exxkEgjrjbkHqG3psV3SI2q+SJqDEC7We3Ylxivk8XNdoZ8jDs4TPHnqCVs8TwNA== + picomatch@^2.0.4: version "2.1.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.1.1.tgz#ecdfbea7704adb5fe6fb47f9866c4c0e15e905c5" @@ -3218,6 +3310,11 @@ plist@^3.0.1: xmlbuilder "^9.0.7" xmldom "0.1.x" +pop-iterate@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/pop-iterate/-/pop-iterate-1.0.1.tgz#ceacfdab4abf353d7a0f2aaa2c1fc7b3f9413ba3" + integrity sha1-zqz9q0q/NT16DyqqLB/Hs/lBO6M= + portfinder@^1.0.23: version "1.0.25" resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.25.tgz#254fd337ffba869f4b9d37edc298059cb4d35eca" @@ -3304,11 +3401,25 @@ punycode@^2.1.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== +q@2.0.x: + version "2.0.3" + resolved "https://registry.yarnpkg.com/q/-/q-2.0.3.tgz#75b8db0255a1a5af82f58c3f3aaa1efec7d0d134" + integrity sha1-dbjbAlWhpa+C9Yw/Oqoe/sfQ0TQ= + dependencies: + asap "^2.0.0" + pop-iterate "^1.0.1" + weak-map "^1.0.5" + qs@6.7.0: version "6.7.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== +qs@^6.9.1: + version "6.9.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.2.tgz#a27b695006544a04bf0e6c6a7e8120778926d5bd" + integrity sha512-2eQ6zajpK7HwqrY1rRtGw5IZvjgtELXzJECaEDuzDFo2jjnIXpJSimzd4qflWZq6bLLi+Zgfj5eDrAzl/lptyg== + qs@~6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" @@ -3324,6 +3435,11 @@ querystring@0.2.0: resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= +querystringify@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" + integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== + range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" @@ -3462,6 +3578,11 @@ require-main-filename@^2.0.0: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -3524,6 +3645,11 @@ rimraf@^3.0.0: dependencies: glob "^7.1.3" +rootpath@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/rootpath/-/rootpath-0.1.2.tgz#5b379a87dca906e9b91d690a599439bef267ea6b" + integrity sha1-Wzeah9ypBum5HWkKWZQ5vvJn6ms= + router@^1.3.1: version "1.3.3" resolved "https://registry.yarnpkg.com/router/-/router-1.3.3.tgz#c142f6b5ea4d6b3359022ca95b6580bd217f89cf" @@ -3581,6 +3707,11 @@ sax@>=0.6.0: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== +scmp@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/scmp/-/scmp-2.1.0.tgz#37b8e197c425bdeb570ab91cc356b311a11f9c9a" + integrity sha512-o/mRQGk9Rcer/jEEw/yw4mwo3EU/NvYvp577/Btqrym9Qy5/MdWGBqipbALgd2lrdWTJ5/gqDusxfnQBxOxT2Q== + semver-diff@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" @@ -4092,6 +4223,23 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= +twilio@^3.41.1: + version "3.41.1" + resolved "https://registry.yarnpkg.com/twilio/-/twilio-3.41.1.tgz#653f2daccad7fe3ac0362acd1a1347e690dd9795" + integrity sha512-YOAuQtb3xELQJDcL+G6ffDRrZeJSlFRph5peudFYcEa9Or5R0x+r8lShXlYl7yP8w7atCWxETSeySLuStEpvhg== + dependencies: + "@types/express" "^4.17.3" + axios "^0.19.2" + dayjs "^1.8.21" + jsonwebtoken "^8.5.1" + lodash "^4.17.15" + q "2.0.x" + qs "^6.9.1" + rootpath "^0.1.2" + scmp "^2.1.0" + url-parse "^1.4.7" + xmlbuilder "^13.0.2" + type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" @@ -4199,6 +4347,14 @@ url-parse-lax@^1.0.0: dependencies: prepend-http "^1.0.1" +url-parse@^1.4.7: + version "1.4.7" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278" + integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + url@0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64" @@ -4276,6 +4432,16 @@ wcwidth@^1.0.1: dependencies: defaults "^1.0.3" +weak-map@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/weak-map/-/weak-map-1.0.5.tgz#79691584d98607f5070bd3b70a40e6bb22e401eb" + integrity sha1-eWkVhNmGB/UHC9O3CkDmuyLkAes= + +whatwg-fetch@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" + integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== + which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" @@ -4381,6 +4547,11 @@ xml2js@0.4.19: sax ">=0.6.0" xmlbuilder "~9.0.1" +xmlbuilder@^13.0.2: + version "13.0.2" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-13.0.2.tgz#02ae33614b6a047d1c32b5389c1fdacb2bce47a7" + integrity sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ== + xmlbuilder@^9.0.7, xmlbuilder@~9.0.1: version "9.0.7" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d"