如何在 twilio 对话中使用 React 正确发送消息?

How to send properly a message in twilio conversation with react?

我有一个 nextjs 项目,我想用 twilio 对话替换 twilio 可编程聊天。

我做了以下步骤:

  1. 我做了一个 API 其中 creates or gets (if it is already created) the conversation and returns to the client the conversation unique name and the token

  2. 获得会话唯一名称和令牌后,我想向客户端发送一条消息。

为此,我执行了以下功能:

import { Client, State } from '@twilio/conversations';
import toast from 'react-hot-toast';

const sendMessageToConversation = async (
  token: string,
  room: string,
  message: string
) => {
  const client = new Client(token);
  client.on('stateChanged', async (state: State) => {
    if (state === 'initialized') {
      try {
        const conversation = await client.getConversationByUniqueName(room);
        await conversation.join();
        if (message && String(message).trim()) {
          await conversation.sendMessage(message);
        }
      } catch {
        toast.error('Unable to create conversation, please reload this page');
      }
    }
  });
};

问题似乎是 const conversation = await client.getConversationByUniqueName(room);,它给出了以下错误:

你认为我做错了什么?

此外,构建一个 API 来发送消息 in this way 是不是更好的主意?由于服务器可能的开销,我会避免这种情况

更新

我尝试发送消息 through API。它有效,并且 return 符合我的预期。有关更多详细信息,我还将在后端放置生成令牌和对话的代码。

我为客户端生成令牌:

import Twilio from 'twilio';
import { config } from '../config';
const client = require('twilio')(
  config.TWILIO_ACCOUNT_SID,
  config.TIWLIO_AUTH_TOKEN
);

const AccessToken = Twilio.jwt.AccessToken;
const ChatGrant = AccessToken.ChatGrant;
const SyncGrant = AccessToken.SyncGrant;

export const tokenGenerator = (identity: string) => {
  const token = new AccessToken(
    config.TWILIO_ACCOUNT_SID,
    config.TWILIO_API_KEY,
    config.TWILIO_API_SECRET
  );

  token.identity = identity || 'unknown';

  if (config.TWILIO_CHAT_SERVICE_SID) {
    const chatGrant = new ChatGrant({
      serviceSid: config.TWILIO_CHAT_SERVICE_SID,
      pushCredentialSid: config.TWILIO_FCM_CREDENTIAL_SID,
    });
    token.addGrant(chatGrant);
  }

  if (config.TWILIO_SYNC_SERVICE_SID) {
    const syncGrant = new SyncGrant({
      serviceSid: config.TWILIO_SYNC_SERVICE_SID || 'default',
    });
    token.addGrant(syncGrant);
  }

  return {
    identity: token.identity,
    token: token.toJwt(),
  };
};

我创建了以下对话:

const client = require('twilio')(
  config.TWILIO_ACCOUNT_SID,
  config.TIWLIO_AUTH_TOKEN
);

export const createTwilioConversation = async (
  partecipantsProfiles: Partial<User>[],
  identity: string
) => {
  const friendlyName: string = partecipantsProfiles
    .map((el) => `${el.first_name} ${el.last_name}`)
    .join(' - ');

  const conversation = (await client.conversations.conversations.create({
    friendlyName,
    uniqueName: uuidv4(),
  })) as TwilioConversationResponse;

  await client.conversations
    .conversations(conversation.sid)
    .participants.create({ identity });

  return conversation;
};

我发送消息的流程是:

我也试过通过 API 发送消息并且它有效。我不明白为什么我仍然无法通过客户端的唯一名称进行对话。也许我应该以不同的方式生成令牌?

这是服务器端发送消息的方法:

export const sendMessage = async (
  conversationSid: string,
  author: string,
  body: string
) => {
  return await client.conversations
    .conversations(conversationSid)
    .messages.create({ author, body });
};

Twilio 有官方博客 Build a Chat App with Twilio Programmable Chat and React.js,请查看一次,

这里是 link - https://www.twilio.com/blog/build-a-chat-app-with-twilio-programmable-chat-and-react

您的问题是您没有使用默认的对话服务,但您没有将服务器端的 API 调用范围限定为您需要的服务。

因此,在 pages/api/utils/conversations 中,您需要将 .services(config.TWILIO_CHAT_SERVICE_SID) 添加到所有 API 调用中。见下文:

export const createTwilioConversation = async (
  chatTo: string,
  myIdentity: string
) => {
  const uniqueName = uuidv4();

  const conversation = (await client.conversations
    .services(config.TWILIO_CHAT_SERVICE_SID)
    .conversations.create({
      friendlyName: `Chat created by ${myIdentity}`,
      uniqueName,
    })) as TwilioConversationResponse;

  await client.conversations
    .services(config.TWILIO_CHAT_SERVICE_SID)
    .conversations(conversation.sid)
    .participants.create({ identity: chatTo });

  await client.conversations
    .services(config.TWILIO_CHAT_SERVICE_SID)
    .conversations(conversation.sid)
    .participants.create({ identity: myIdentity });

  return conversation;
};

export const sendMessage = async (
  conversationSid: string,
  author: string,
  body: string
) => {
  return await client.conversations
    .services(config.TWILIO_CHAT_SERVICE_SID)
    .conversations(conversationSid)
    .messages.create({ author, body });
};

完成此操作后,您还需要做另一件事。因为您使用 REST API 将您的参与者添加到对话中,所以您不需要 join front-end 中的对话。所以你可以删除行

await conversation.join();

来自 src/twilio/index.ts.

最后一件事,如果您注销 error.body 而不仅仅是 errorerror.message.[=20=,您可以在 front-end 中获得更好的错误消息]

      try {
        const conversation = await client.getConversationByUniqueName(room);
        if (message && String(message).trim()) {
          await conversation.sendMessage(message);
        }
      } catch (error) {
        console.log("error", error);
        console.log("error body", error.body);
        toast.error("Unable to create conversation, please reload this page");
      }