Skip to content

Commit

Permalink
feat: add video-chat
Browse files Browse the repository at this point in the history
  • Loading branch information
ingridpacheco committed Sep 2, 2020
1 parent b32535f commit f145e00
Show file tree
Hide file tree
Showing 17 changed files with 699 additions and 56 deletions.
3 changes: 3 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
REACT_APP_AUTH0_DOMAIN=clinicall.us.auth0.com
REACT_APP_AUTH0_CLIENT_ID=i7YJaB8vka2TJGyWKDJQtm0X07KNjFP4
SKIP_PREFLIGHT_CHECK=true
TWILIO_ACCOUNT_SID= "AC7d0f4b2ab93382fa387732772e2fadf8"
TWILIO_API_KEY= "SK2494b65a32e9e545b07ce0c8c0100474"
TWILIO_API_SECRET= "RBNeyZn7rQRZLvqE3QT23yqMzlST0tdA"
45 changes: 20 additions & 25 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@material-ui/core": "^4.11.0",
"@auth0/auth0-react": "^1.0.0",
"@material-ui/core": "^4.11.0",
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
Expand All @@ -17,40 +17,35 @@
"react-dom": "^16.13.1",
"react-router-dom": "^5.2.0",
"react-rtc-real": "^1.11.22",
"react-scripts": "3.4.3"
"react-scripts": "3.4.3",
"twilio-video": "^2.7.2"
},
"devDependencies": {
"@types/express": "^4.17.2",
"@types/socket.io": "^2.1.4",
"eslint-config-airbnb": "^18.2.0",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-import-helpers": "^1.1.0",
"eslint-plugin-jsx-a11y": "^6.3.1",
"eslint-plugin-react": "^7.20.6",
"eslint-plugin-react-hooks": "^4.1.0"
"body-parser": "^1.19.0",
"express": "^4.17.1",
"express-pino-logger": "^4.0.0",
"node-env-run": "^3.0.2",
"nodemon": "^1.19.3",
"npm-run-all": "^4.1.5",
"pino-colada": "^1.4.5",
"twilio": "^3.33.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"client": "cd client && npm start",
"dev": "nodemon --watch './server/**/*.js' --exec 'babel-node' ./server/server.js",
"server": "babel-node server/server.js"
"server": "node-env-run server --exec nodemon | pino-colada",
"dev": "run-p server start"
},
"proxy": "http://localhost:3001",
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
]
}
10 changes: 10 additions & 0 deletions server/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module.exports = {
twilio: {
accountSid: process.env.TWILIO_ACCOUNT_SID,
apiKey: process.env.TWILIO_API_KEY,
apiSecret: process.env.TWILIO_API_SECRET,
chatService: process.env.TWILIO_CHAT_SERVICE_SID,
outgoingApplicationSid: process.env.TWILIO_TWIML_APP_SID,
incomingAllow: process.env.TWILIO_ALLOW_INCOMING_CALLS === "true"
}
};
67 changes: 67 additions & 0 deletions server/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
const config = require('./config');
const express = require('express');
const bodyParser = require('body-parser');
const pino = require('express-pino-logger')();
const { chatToken, videoToken, voiceToken } = require('./tokens');

const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(pino);

const sendTokenResponse = (token, res) => {
res.set('Content-Type', 'application/json');
res.send(
JSON.stringify({
token: token.toJwt()
})
);
};

app.get('/api/greeting', (req, res) => {
const name = req.query.name || 'World';
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({ greeting: `Hello ${name}!` }));
});

app.get('/chat/token', (req, res) => {
const identity = req.query.identity;
const token = chatToken(identity, config);
sendTokenResponse(token, res);
});

app.post('/chat/token', (req, res) => {
const identity = req.body.identity;
const token = chatToken(identity, config);
sendTokenResponse(token, res);
});

app.get('/video/token', (req, res) => {
const identity = req.query.identity;
const room = req.query.room;
const token = videoToken(identity, room, config);
sendTokenResponse(token, res);
});

app.post('/video/token', (req, res) => {
const identity = req.body.identity;
const room = req.body.room;
const token = videoToken(identity, room, config);
sendTokenResponse(token, res);
});

app.get('/voice/token', (req, res) => {
const identity = req.body.identity;
const token = voiceToken(identity, config);
sendTokenResponse(token, res);
});

app.post('/voice/token', (req, res) => {
const identity = req.body.identity;
const token = voiceToken(identity, config);
sendTokenResponse(token, res);
});

app.listen(3001, () =>
console.log('Express server is running on localhost:3001')
);
54 changes: 54 additions & 0 deletions server/tokens.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const twilio = require("twilio");
const AccessToken = twilio.jwt.AccessToken;
const { ChatGrant, VideoGrant, VoiceGrant } = AccessToken;

const generateToken = config => {
return new AccessToken(
config.twilio.accountSid,
config.twilio.apiKey,
config.twilio.apiSecret
);
};

const chatToken = (identity, config) => {
const chatGrant = new ChatGrant({
serviceSid: config.twilio.chatService
});
const token = generateToken(config);
token.addGrant(chatGrant);
token.identity = identity;
return token;
};

const videoToken = (identity, room, config) => {
let videoGrant;
if (typeof room !== "undefined") {
videoGrant = new VideoGrant({ room });
} else {
videoGrant = new VideoGrant();
}
const token = generateToken(config);
token.addGrant(videoGrant);
token.identity = identity;
return token;
};

const voiceToken = (identity, config) => {
let voiceGrant;
if (typeof config.twilio.outgoingApplicationSid !== "undefined") {
voiceGrant = new VoiceGrant({
outgoingApplicationSid: config.twilio.outgoingApplicationSid,
incomingAllow: config.twilio.incomingAllow
});
} else {
voiceGrant = new VoiceGrant({
incomingAllow: config.twilio.incomingAllow
});
}
const token = generateToken(config);
token.addGrant(voiceGrant);
token.identity = identity;
return token;
};

module.exports = { chatToken, videoToken, voiceToken };
26 changes: 0 additions & 26 deletions src/App.scss
Original file line number Diff line number Diff line change
@@ -1,30 +1,4 @@
.App {
text-align: center;
}

.App-logo {
height: 40vmin;
pointer-events: none;
}

.App-header {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}

.App-link {
color: #61dafb;
}

@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
10 changes: 5 additions & 5 deletions src/App.test.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from 'react';
import { render } from '@testing-library/react';
import ReactDOM from 'react-dom';
import App from './App';

test('renders learn react link', () => {
const { getByText } = render(<App />);
const linkElement = getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
ReactDOM.unmountComponentAtNode(div);
});
2 changes: 2 additions & 0 deletions src/Routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useAuth0 } from "@auth0/auth0-react"

import Home from "./Home"
import Profile from "./pages/Profile"
import Chat from './VideoChat'

function Routes() {
const { isAuthenticated } = useAuth0()
Expand All @@ -20,6 +21,7 @@ function Routes() {
))}
/>
<Route path="/profile" component={Profile} />
<Route path="/chat" component={Chat} />
</BrowserRouter>
)
}
Expand Down
Loading

0 comments on commit f145e00

Please sign in to comment.