Cách tạo ứng dụng trò chuyện thời gian thực với Twilio-Conversation?

May 03 2023
Hãy cùng khám phá sức mạnh của trò chuyện Twilio bằng JavaScript SDK để xây dựng một ứng dụng trò chuyện đáng tin cậy và có thể mở rộng. Bài viết này sẽ giúp bạn tích hợp một ứng dụng trò chuyện với API hội thoại của Twilio ở góc cạnh, nhưng không phải vậy; bạn có thể tìm thêm các trường hợp sử dụng hoặc ví dụ như đã đề cập tại đây.

Hãy cùng khám phá sức mạnh của trò chuyện Twilio bằng JavaScript SDK để xây dựng một ứng dụng trò chuyện đáng tin cậy và có thể mở rộng.

Bài viết này sẽ giúp bạn tích hợp một ứng dụng trò chuyện với API hội thoại của Twilio ở góc cạnh, nhưng không phải vậy; bạn có thể tìm thêm các trường hợp sử dụng hoặc ví dụ như đã đề cập ở đây .

Bây giờ, hãy bắt đầu và tạo một ứng dụng trò chuyện mẫu để chứng minh điều tương tự.

Tích hợp Twilio-Conversation với Angular

điều kiện tiên quyết

  • Nút J
  • Trình quản lý gói: npm
  • Tạo một tài khoản Twilio miễn phí để bắt đầu sử dụng cùng một tài khoản
  • CLI góc

Hãy thiết lập mã Backend trước

Chạy các lệnh được đề cập bên dưới để tạo một dự án NodeJS mới, 'chat-backend.'

mkdir chat-backend
cd chat-backend
npm init

npm i express
npm i dotenv
npm i twilio

TWILIO_ACCOUNT_SID=
TWILIO_AUTH_TOKEN=
TWILIO_SERVICE_SID=
TWILIO_API_KEY=
TWILIO_API_SECRET=

index.js

require('dotenv').config();
const express = require("express");
var app = express();
const chat = require('./chat');

app.use(function(req, res, next) {
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
    res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
    res.setHeader('Access-Control-Allow-Credentials', true);
    next();
});

app.get("/", function (request, response) {
    response.send("Hello World!");
})

app.get("/getToken", function (request, response) {
    let token = chat.getToken(request.query.userName);
   response.send(JSON.stringify(token));
})

app.listen(3000, function () {
    console.log("Started application on port %d", 3000);
});

const accountSid = process.env.TWILIO_ACCOUNT_SID;
const authToken = process.env.TWILIO_AUTH_TOKEN;
const serviceSid = process.env.TWILIO_SERVICE_SID;
const apiKey = process.env.TWILIO_API_KEY;
const apiSecret = process.env.TWILIO_API_SECRET;
const client = require('twilio')(accountSid, authToken);

// Create a twilio access token
function getToken(identity) {
    const AccessToken = require('twilio').jwt.AccessToken;
    const ChatGrant = AccessToken.ChatGrant;

    const chatGrant = new ChatGrant({
        serviceSid: serviceSid,
    });
    const token = new AccessToken(
        accountSid,
        apiKey,
        apiSecret,
        { 
            identity: identity,
            ttl: 3600
        }
    );

    token.addGrant(chatGrant); 
    return token.toJwt();
}

module.exports = {getToken};

npm start

Chạy các lệnh được đề cập bên dưới để tạo một dự án góc cạnh mới với angular-cli

ng new twilio-chat-example
cd twilio-chat-example
ng serve

npm install --save @twilio/conversations

ng g c chats

connectTwilio() {
    this.isLoading = true;
    this.getToken().subscribe(token => {
      this.client = new Client(token);
      this.isLoading = false;
      this.listenToEvents();
    }, error => console.log(error));
  }

Lắng nghe sự kiện tokenAboutToExpire & tokenExpired để gia hạn mã thông báo đã tạo và tiếp tục làm việc với các dịch vụ Twilio.

listenToEvents() {
    this.client.on('initialized', () => {
      console.log('Client initialized');
      this.fetchUserChats();
    });

    this.client.on('initFailed', (error: any) => {
      console.log('Client initialization failed: ', error);
    });

    this.client.on('connectionStateChanged', (state: ConnectionState) => {
      console.log('Connection state change: ', state);
    });

    this.client.on('connectionError', (error: any) => {
      console.log('Connection error: ', error);
    });

    this.client.on('tokenAboutToExpire', () => {
      console.log('About to expire');
      this.getToken().subscribe(async (token) => {
        this.client = await this.client.updateToken(token);
      })
    });

    this.client.on('tokenExpired', () => {
      console.log('Token expired');
      this.client.removeAllListeners();
      this.connectTwilio();
    });

    this.client.on('conversationAdded', (conv: Conversation) => {
      setTimeout(async () => {
        if (conv.dateCreated && conv.dateCreated > this.currentTime) {
          console.log('Conversation added', conv);
          await conv.setAllMessagesUnread();
          let newChat = {
            chat: conv,
            unreadCount: 0,
            lastMessage: ''
          }
          this.chatList = [newChat,...this.chatList];
        }
      }, 500);
    });

    this.client.on('messageAdded', async (msg: Message) => {
      console.log('Message added', msg);
      if (this.currentConversation && this.currentConversation.sid === msg.conversation.sid) {
        this.messages.push(msg);
        await this.currentConversation.updateLastReadMessageIndex(msg.index);
        this.chatList = this.chatList.map(el => {
          if(el.chat.sid === this.currentConversation.sid){
            el.lastMessage = msg.body;
          }
          return el;
        });
      } else {
        this.chatList = this.chatList.map(el => {
          if(el.chat.sid === msg.conversation.sid){
            el.lastMessage = msg.body;
            el.unreadCount++;
          }
          return el;
        });
      }
    });

    this.client.on('typingStarted', (user: Participant) => {
      console.log('typing..', user);
      if (user.conversation.sid === this.currentConversation.sid) this.isTyping = true;
    });

    this.client.on('typingEnded', (user: Participant) => {
      console.log('typing end..', user);
      if (user.conversation.sid === this.currentConversation.sid) this.isTyping = false;
    });
  }

fetchUserChats() {
    this.isLoading = true;
    this.client.getSubscribedConversations().then(convs => {
      let chats:any = [...convs.items];
      chats.forEach( async (chat:Conversation) => {
        let obj = {
          chat: chat,
          unreadCount: await chat.getUnreadMessagesCount(),
          lastMessage: (await chat.getMessages()).items[chat.lastReadMessageIndex || 0].body
        }
        this.chatList.push(obj);
      })
      this.isLoading = false;
    }).catch(error => console.log(error));
  }

newChat() {
    this.isLoading = true;
    this.client.getUser(this.newUser).then(res => {
      this.client.createConversation({
        friendlyName: `${this.newUser}-${this.userName}`,
      }).then(async (channel: Conversation) => {
        channel.join().then(async () => {
          await channel.setAllMessagesUnread();
          channel.add(this.newUser).then(() => {
            this.currentConversation = channel;
            this.openChat(channel);
            this.scrollToBottom();
            this.isLoading = false;
          })
        });
      }).catch(error => console.log(error));
    }).catch(err => {
      this.isLoading = false;
      this.error = 'User not found in Twilio';
      setTimeout(() => {
        this.error = null;
      }, 2000);
      this.newUser = null;
    });
  }

sendMessage() {
    this.currentConversation.sendMessage(this.message).then(result => {
      this.message = '';
    }).catch(err => console.log(err));
  }

Lưu ý: triển khai tải thông báo trên cuộn vì getMessages sẽ trả về 30 mục cùng một lúc và triển khai tương tự để tìm nạp cuộc hội thoại của người dùng.

fetchMessages(skip?: number) {
    this.isLoading = true;
    this.currentConversation.getMessages(30, skip).then(async (result) => {
      this.messages = [...result.items, ...this.messages];
      if (!skip) {
        let resetTo = this.messages.length >= 1 ? this.messages[this.messages.length - 1].index : 0;
        await this.currentConversation.updateLastReadMessageIndex(resetTo);
        this.chatList = this.chatList.map( el => {
          if(el.chat.sid == this.currentConversation.sid){
            el.unreadCount = 0;
          }
          return el;
        })
      }
      this.isLoading = false;
    }).catch(error => {
      this.isLoading = false;
      console.log(error)
    });
  }

Đây là một ví dụ cơ bản về việc tạo một ứng dụng trò chuyện với các cuộc hội thoại Twilio. Bạn có thể xem những thứ khác trên tài liệu chính thức của nó để đính kèm phương tiện, đóng trò chuyện (quản lý trạng thái hội thoại), chỉ báo khả năng tiếp cận, làm việc với các kênh bên ngoài, v.v.

Những điều cần ghi nhớ

  • Không thêm nhiều người nghe cho cùng một sự kiện để tránh mọi hành vi sai trái
  • Kiểm tra giới hạn hội thoại Twilio một lần trước khi tạo luồng logic theo trường hợp sử dụng của bạn
  • Hãy xem gói giá của Twilio , vì đây là dịch vụ trả phí.

Người giới thiệu

Tài liệu:https://www.twilio.com/docs/conversations
Ví dụ: Xem video ví dụ trên liên kết ví dụ GitHub đã cho
(Frontend)https://github.com/Khushbu-2112/Twilio-chat-frontend-Example
(phụ trợ)https://github.com/Khushbu-2112/Twilio-chat-backend-Example