SDK do Amazon IVS Chat Client Messaging: Tutorial de JavaScript, parte 1: salas de chat - Amazon IVS

SDK do Amazon IVS Chat Client Messaging: Tutorial de JavaScript, parte 1: salas de chat

Esta é a primeira de um tutorial de duas partes. Você aprenderá os fundamentos do trabalho com o SDK JavaScript do Amazon IVS Chat Client Messaging criando uma aplicação totalmente funcional usando JavaScript/TypeScript. Chamamos a aplicação de Chatterbox.

O público-alvo são desenvolvedores experientes, mas iniciantes no SDK Amazon IVS Chat Messaging. Você deve se sentir confortável com a linguagem de programação JavaScript/TypeScript e a biblioteca React.

Para resumir, vamos nos referir ao SDK JavaScript do Amazon IVS Chat Client Messaging como o SDK do Chat JS.

Observação: em alguns casos, os exemplos de código para JavaScript e TypeScript são idênticos, então eles são combinados.

Esta primeira parte do tutorial está dividida em várias seções:

Para obter a documentação completa do SDK, comece com o SDK de Mensagens para Clientes do Chat do Amazon IVS (aqui no Guia do usuário do Chat do Amazon IVS) e a Referência de Mensagens para Clientes do Chat: SDK para JavaScript (no GitHub).

Pré-requisitos

Configure um servidor local de autenticação/autorização

Sua aplicação de backend é responsável por criar salas de chat e gerar os tokens de chat necessários para que o SDK do Chat JS autentique e autorize seus clientes em suas salas de chat. Você deverá usar seu próprio backend, pois não é possível armazenar com segurança as chaves da AWS em uma aplicação móvel. Invasores sofisticados podem extraí-las e obter acesso à sua conta da AWS.

Consulte Criar um token de chat em Introdução ao Amazon IVS Chat. Conforme mostrado no fluxograma, sua aplicação do lado do servidor é responsável por criar um token de chat. Isso significa que sua aplicação deve fornecer seu próprio meio de gerar um token de chat solicitando-o da sua aplicação a partir do lado do servidor.

Nesta seção, você aprenderá os fundamentos da criação de um provedor de tokens em seu backend. Usamos a estrutura expressa para criar um servidor local ativo que gerencia a criação de tokens de chat usando seu ambiente local da AWS.

Crie um projeto npm vazio usando o NPM. Crie um diretório para manter sua aplicação e torne-o seu diretório de trabalho:

$ mkdir backend & cd backend

Use npm init para criar um arquivo package.json para sua aplicação:

$ npm init

Esse comando solicita várias coisas, incluindo o nome e a versão da sua aplicação. Por enquanto, basta pressionar RETURN para aceitar os padrões da maioria deles, com a seguinte exceção:

entry point: (index.js)

Pressione RETURN para aceitar o nome de arquivo padrão sugerido index.js ou digite o que você quiser que seja o nome do arquivo principal.

Agora instale as dependências necessárias:

$ npm install express aws-sdk cors dotenv

aws-sdk requer variáveis de ambiente de configuração que são carregadas automaticamente de um arquivo chamado .env localizado no diretório raiz. Para configurá-lo, crie um novo arquivo chamado .env e preencha as informações de configuração ausentes:

# .env # The region to send service requests to. AWS_REGION=us-west-2 # Access keys use an access key ID and secret access key # that you use to sign programmatic requests to AWS. # AWS access key ID. AWS_ACCESS_KEY_ID=... # AWS secret access key. AWS_SECRET_ACCESS_KEY=...

Agora, criamos um arquivo de ponto de entrada no diretório raiz com o nome que você inseriu acima no comando npm init. Nesse caso, usamos index.js e importamos todos os pacotes necessários:

// index.js import express from 'express'; import AWS from 'aws-sdk'; import 'dotenv/config'; import cors from 'cors';

Agora, crie uma nova instância de express:

const app = express(); const port = 3000; app.use(express.json()); app.use(cors({ origin: ['http://127.0.0.1:5173'] }));

Depois disso, será possível criar seu primeiro método POST de endpoint para o provedor do token. Pegue os parâmetros necessários do corpo da solicitação (roomId, userId, capabilities e sessionDurationInMinutes):

app.post('/create_chat_token', (req, res) => { const { roomIdentifier, userId, capabilities, sessionDurationInMinutes } = req.body || {}; });

Adicione a validação dos campos obrigatórios:

app.post('/create_chat_token', (req, res) => { const { roomIdentifier, userId, capabilities, sessionDurationInMinutes } = req.body || {}; if (!roomIdentifier || !userId) { res.status(400).json({ error: 'Missing parameters: `roomIdentifier`, `userId`' }); return; } });

Depois de preparar o método POST, integramos createChatToken com aws-sdk para a funcionalidade principal de autenticação/autorização:

app.post('/create_chat_token', (req, res) => { const { roomIdentifier, userId, capabilities, sessionDurationInMinutes } = req.body || {}; if (!roomIdentifier || !userId || !capabilities) { res.status(400).json({ error: 'Missing parameters: `roomIdentifier`, `userId`, `capabilities`' }); return; } ivsChat.createChatToken({ roomIdentifier, userId, capabilities, sessionDurationInMinutes }, (error, data) => { if (error) { console.log(error); res.status(500).send(error.code); } else if (data.token) { const { token, sessionExpirationTime, tokenExpirationTime } = data; console.log(`Retrieved Chat Token: ${JSON.stringify(data, null, 2)}`); res.json({ token, sessionExpirationTime, tokenExpirationTime }); } }); });

No final do arquivo, adicione um receptor de portas para sua aplicação express:

app.listen(port, () => { console.log(`Backend listening on port ${port}`); });

Agora é possível executar o servidor com a linha de comando a seguir na raiz do projeto:

$ node index.js

Dica: este servidor aceita solicitações de URL em https://localhost:3000.

Crie um projeto de Chatterbox

Primeiro você cria o projeto React chamado chatterbox. Execute este comando:

npx create-react-app chatterbox

É possível integrar o SDK do Chat Client Messaging JS por meio do Gerenciador de pacotes de nó ou do Gerenciador de pacotes Yarn:

  • Npm: npm install amazon-ivs-chat-messaging

  • Yarn: yarn add amazon-ivs-chat-messaging

Conectar a uma sala de chat

Aqui você cria uma ChatRoom e se conecta a ela usando métodos assíncronos. A classe ChatRoom gerencia a conexão do usuário com o SDK do Chat JS. Para se conectar com sucesso a uma sala de chat, você deve fornecer uma instância de ChatToken dentro da sua aplicação React.

Navegue até o arquivo App criado no projeto chatterbox padrão e exclua tudo entre as duas etiquetas <div>. Nenhum código pré-preenchido é necessário. Neste ponto, a nossa App está bem vazia.

// App.jsx / App.tsx import * as React from 'react'; export default function App() { return <div>Hello!</div>; }

Crie uma nova instância de ChatRoom e passe-a para o estado usando o gancho useState. Ela exige a passagem de regionOrUrl (a região da AWS na qual sua sala de chat está hospedada) e tokenProvider (usado para o fluxo de autenticação/autorização de backend criado nas etapas subsequentes).

Importante: você deve usar a mesma região da AWS em que criou a sala em Conceitos básicos do Amazon IVS Chat. A API é um serviço regional da AWS. Para obter uma lista das regiões com suporte e dos endpoints do serviço HTTPS do Amazon IVS Chat, consulte a página de Regiões do Amazon IVS Chat.

// App.jsx / App.tsx import React, { useState } from 'react'; import { ChatRoom } from 'amazon-ivs-chat-messaging'; export default function App() { const [room] = useState(() => new ChatRoom({ regionOrUrl: process.env.REGION as string, tokenProvider: () => {}, }), ); return <div>Hello!</div>; }

Crie um provedor de tokens

Como próxima etapa, precisamos criar uma função tokenProvider sem parâmetros que seja exigida pelo construtor ChatRoom. Primeiro, criaremos uma função fetchChatToken que fará uma solicitação POST para a aplicação de backend que você configurou em Configure um servidor local de autenticação/autorização. Os tokens de chat contêm as informações necessárias para que o SDK estabeleça uma conexão com a sala de chat com êxito. A API do Chat usa esses tokens como uma forma segura de validar a identidade, os recursos de um usuário em uma sala de chat e a duração da sessão.

No navegador do projeto, crie um novo arquivo TypeScript/JavaScript chamado fetchChatToken. Crie uma solicitação de busca para a aplicação backend e retorne o objeto ChatToken da resposta. Adicione as propriedades do corpo da solicitação necessárias para a criação de um token de chat. Use as regras definidas para nomes do recurso da Amazon (ARNs). Essas propriedades estão documentadas no endpoint CreateChatToken.

Observação: o URL que você está usando aqui é o mesmo URL que seu servidor local criou quando você executou a aplicação de backend.

TypeScript
// fetchChatToken.ts import { ChatToken } from 'amazon-ivs-chat-messaging'; type UserCapability = 'DELETE_MESSAGE' | 'DISCONNECT_USER' | 'SEND_MESSAGE'; export async function fetchChatToken( userId: string, capabilities: UserCapability[] = [], attributes?: Record<string, string>, sessionDurationInMinutes?: number, ): Promise<ChatToken> { const response = await fetch(`${process.env.BACKEND_BASE_URL}/create_chat_token`, { method: 'POST', headers: { Accept: 'application/json', 'Content-Type': 'application/json', }, body: JSON.stringify({ userId, roomIdentifier: process.env.ROOM_ID, capabilities, sessionDurationInMinutes, attributes }), }); const token = await response.json(); return { ...token, sessionExpirationTime: new Date(token.sessionExpirationTime), tokenExpirationTime: new Date(token.tokenExpirationTime), }; }
JavaScript
// fetchChatToken.js export async function fetchChatToken( userId, capabilities = [], attributes, sessionDurationInMinutes) { const response = await fetch(`${process.env.BACKEND_BASE_URL}/create_chat_token`, { method: 'POST', headers: { Accept: 'application/json', 'Content-Type': 'application/json', }, body: JSON.stringify({ userId, roomIdentifier: process.env.ROOM_ID, capabilities, sessionDurationInMinutes, attributes }), }); const token = await response.json(); return { ...token, sessionExpirationTime: new Date(token.sessionExpirationTime), tokenExpirationTime: new Date(token.tokenExpirationTime), }; }

Observe as atualizações de conexão

Reagir às mudanças no estado da conexão de uma sala de chat é parte essencial da criação de uma aplicação de chat. Vamos começar assinando eventos relevantes:

// App.jsx / App.tsx import React, { useState, useEffect } from 'react'; import { ChatRoom } from 'amazon-ivs-chat-messaging'; import { fetchChatToken } from './fetchChatToken'; export default function App() { const [room] = useState( () => new ChatRoom({ regionOrUrl: process.env.REGION as string, tokenProvider: () => fetchChatToken('Mike', ['SEND_MESSAGE']), }), ); useEffect(() => { const unsubscribeOnConnecting = room.addListener('connecting', () => {}); const unsubscribeOnConnected = room.addListener('connect', () => {}); const unsubscribeOnDisconnected = room.addListener('disconnect', () => {}); return () => { // Clean up subscriptions. unsubscribeOnConnecting(); unsubscribeOnConnected(); unsubscribeOnDisconnected(); }; }, [room]); return <div>Hello!</div>; }

Em seguida, precisamos fornecer a capacidade de ler o estado da conexão. Usamos nosso hook useState para criar algum estado local em App e definir o estado da conexão dentro de cada receptor.

TypeScript
// App.tsx import React, { useState, useEffect } from 'react'; import { ChatRoom, ConnectionState } from 'amazon-ivs-chat-messaging'; import { fetchChatToken } from './fetchChatToken'; export default function App() { const [room] = useState( () => new ChatRoom({ regionOrUrl: process.env.REGION as string, tokenProvider: () => fetchChatToken('Mike', ['SEND_MESSAGE']), }), ); const [connectionState, setConnectionState] = useState<ConnectionState>('disconnected'); useEffect(() => { const unsubscribeOnConnecting = room.addListener('connecting', () => { setConnectionState('connecting'); }); const unsubscribeOnConnected = room.addListener('connect', () => { setConnectionState('connected'); }); const unsubscribeOnDisconnected = room.addListener('disconnect', () => { setConnectionState('disconnected'); }); return () => { unsubscribeOnConnecting(); unsubscribeOnConnected(); unsubscribeOnDisconnected(); }; }, [room]); return <div>Hello!</div>; }
JavaScript
// App.jsx import React, { useState, useEffect } from 'react'; import { ChatRoom } from 'amazon-ivs-chat-messaging'; import { fetchChatToken } from './fetchChatToken'; export default function App() { const [room] = useState( () => new ChatRoom({ regionOrUrl: process.env.REGION, tokenProvider: () => fetchChatToken('Mike', ['SEND_MESSAGE']), }), ); const [connectionState, setConnectionState] = useState('disconnected'); useEffect(() => { const unsubscribeOnConnecting = room.addListener('connecting', () => { setConnectionState('connecting'); }); const unsubscribeOnConnected = room.addListener('connect', () => { setConnectionState('connected'); }); const unsubscribeOnDisconnected = room.addListener('disconnect', () => { setConnectionState('disconnected'); }); return () => { unsubscribeOnConnecting(); unsubscribeOnConnected(); unsubscribeOnDisconnected(); }; }, [room]); return <div>Hello!</div>; }

Depois de se inscrever no estado da conexão, exiba o estado da conexão e conecte-se à sala de chat usando o método room.connect dentro do gancho useEffect:

// App.jsx / App.tsx // ... useEffect(() => { const unsubscribeOnConnecting = room.addListener('connecting', () => { setConnectionState('connecting'); }); const unsubscribeOnConnected = room.addListener('connect', () => { setConnectionState('connected'); }); const unsubscribeOnDisconnected = room.addListener('disconnect', () => { setConnectionState('disconnected'); }); room.connect(); return () => { unsubscribeOnConnecting(); unsubscribeOnConnected(); unsubscribeOnDisconnected(); }; }, [room]); // ... return ( <div> <h4>Connection State: {connectionState}</h4> </div> ); // ...

Você implementou com êxito uma conexão de sala de chat.

Crie um componente do botão Enviar

Nesta seção, você criará um botão de envio que tem um design diferente para cada estado de conexão. O botão de envio facilita enviar mensagens em uma sala de chat. Ele também serve como um indicador visual de se/quando as mensagens podem ser enviadas; por exemplo, em caso de conexões perdidas ou sessões de chat expiradas.

Primeiro, crie um novo arquivo no diretório src do seu projeto do Chatterbox e dê a ele o nome SendButton. Em seguida, crie um componente que exibirá um botão para sua aplicação de chat. Exporte seu SendButton e importe-o para App. No <div></div> vazio, adicione <SendButton />.

TypeScript
// SendButton.tsx import React from 'react'; interface Props { onPress?: () => void; disabled?: boolean; } export const SendButton = ({ onPress, disabled }: Props) => { return ( <button disabled={disabled} onClick={onPress}> Send </button> ); }; // App.tsx import { SendButton } from './SendButton'; // ... return ( <div> <div>Connection State: {connectionState}</div> <SendButton /> </div> );
JavaScript
// SendButton.jsx import React from 'react'; export const SendButton = ({ onPress, disabled }) => { return ( <button disabled={disabled} onClick={onPress}> Send </button> ); }; // App.jsx import { SendButton } from './SendButton'; // ... return ( <div> <div>Connection State: {connectionState}</div> <SendButton /> </div> );

Em seguida, em App, defina uma função chamada onMessageSend e passe-a para a propriedade SendButton onPress. Defina outra variável chamada isSendDisabled (que impede o envio de mensagens quando a sala não estiver conectada) e passe-a para a propriedade SendButton disabled.

// App.jsx / App.tsx // ... const onMessageSend = () => {}; const isSendDisabled = connectionState !== 'connected'; return ( <div> <div>Connection State: {connectionState}</div> <SendButton disabled={isSendDisabled} onPress={onMessageSend} /> </div> ); // ...

Crie uma entrada de mensagem

A barra de mensagens do Chatterbox é o componente com o qual você interagirá para enviar mensagens para uma sala de chat. Normalmente, ela contém uma entrada de texto para redigir sua mensagem e um botão para enviar sua mensagem.

Para criar um componente MessageInput, primeiro crie um novo arquivo no diretório src e dê a ele o nome MessageInput. Em seguida, crie um componente de entrada controlada que exibirá uma entrada para sua aplicação de chat. Exporte sua MessageInput e importe-a para App (acima do <SendButton />).

Crie um novo estado chamado messageToSend usando o hook useState, com uma string vazia como valor padrão. No corpo da sua aplicação, passe messageToSend para o value de MessageInput e passe setMessageToSend para a propriedade onMessageChange:

TypeScript
// MessageInput.tsx import * as React from 'react'; interface Props { value?: string; onValueChange?: (value: string) => void; } export const MessageInput = ({ value, onValueChange }: Props) => { return ( <input type="text" value={value} onChange={(e) => onValueChange?.(e.target.value)} placeholder="Send a message" /> ); }; // App.tsx // ... import { MessageInput } from './MessageInput'; // ... export default function App() { const [messageToSend, setMessageToSend] = useState(''); // ... return ( <div> <h4>Connection State: {connectionState}</h4> <MessageInput value={messageToSend} onMessageChange={setMessageToSend} /> <SendButton disabled={isSendDisabled} onPress={onMessageSend} /> </div> );
JavaScript
// MessageInput.jsx import * as React from 'react'; export const MessageInput = ({ value, onValueChange }) => { return ( <input type="text" value={value} onChange={(e) => onValueChange?.(e.target.value)} placeholder="Send a message" /> ); }; // App.jsx // ... import { MessageInput } from './MessageInput'; // ... export default function App() { const [messageToSend, setMessageToSend] = useState(''); // ... return ( <div> <h4>Connection State: {connectionState}</h4> <MessageInput value={messageToSend} onMessageChange={setMessageToSend} /> <SendButton disabled={isSendDisabled} onPress={onMessageSend} /> </div> );

Próximos Passos

Agora que você terminou de criar uma barra de mensagens para o Chatterbox, vá para a parte 2 deste tutorial de JavaScript, mensagens e eventos.