如何在 twilio 对话中使用 React 正确发送消息?
How to send properly a message in twilio conversation with react?
我有一个 nextjs 项目,我想用 twilio 对话替换 twilio 可编程聊天。
我做了以下步骤:
我做了一个 API 其中 creates or gets (if it is already created) the conversation and returns to the client the conversation unique name and the token
获得会话唯一名称和令牌后,我想向客户端发送一条消息。
为此,我执行了以下功能:
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 创建一个对话,执行上面的函数和 return 房间唯一名称和令牌。我还将房间唯一名称、参与者和其他信息存储到我的数据库中。我只对第一条消息这样做。如果一个用户已经与另一个用户聊天,那么我不再创建对话,但我 return 存储的唯一名称 + 生成的令牌和我 get/send 消息客户端
我也试过通过 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
而不仅仅是 error
或 error.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");
}
我有一个 nextjs 项目,我想用 twilio 对话替换 twilio 可编程聊天。
我做了以下步骤:
我做了一个 API 其中 creates or gets (if it is already created) the conversation and returns to the client the conversation unique name and the token
获得会话唯一名称和令牌后,我想向客户端发送一条消息。
为此,我执行了以下功能:
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 创建一个对话,执行上面的函数和 return 房间唯一名称和令牌。我还将房间唯一名称、参与者和其他信息存储到我的数据库中。我只对第一条消息这样做。如果一个用户已经与另一个用户聊天,那么我不再创建对话,但我 return 存储的唯一名称 + 生成的令牌和我 get/send 消息客户端
我也试过通过 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
而不仅仅是 error
或 error.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");
}