Tworzenie obrazów z kodu HTML do dynamicznego tworzenia kart rozszerzonych

Jednym z najbardziej wszechstronnych typów treści w RCS Business Messaging jest karta informacyjna. Dzięki karcie informacyjnej możesz w ramach jednej wiadomości wysyłać fragmenty powiązanych informacji, w tym obraz lub film, tytuł, opis i maksymalnie 4 sugerowane odpowiedzi lub działania.

Oddzielne karty rozszerzone i karuzele kart rozszerzonych to funkcje, które pomagają tworzyć atrakcyjne reklamy dla użytkowników. Działają one dobrze, o ile do udostępniania zdjęć są statyczne obrazy, np. kupon lub produkt. Co się jednak dzieje, gdy musisz wysyłać treści dynamiczne na podstawie informacji o użytkowniku, takich jak karta pokładowa?

W tym artykule pokażę, jak tworzyć obrazy na żywo za pomocą HTML i umieszczać je na kartach informacyjnych wysyłanych przez agenta. Na początek zobaczmy, jak przekonwertować HTML na obraz.

Z HTML do obrazu

HTML świetnie nadaje się do tworzenia kombinacji tekstu i multimediów. Jeśli jesteś deweloperem i chcemy utworzyć usługę służącą do wysyłania użytkownikom kart pokładowych, wykresów wykorzystania danych lub innych informacji o użytkownikach, prawdopodobnie zostanie użyte narzędzie HTML wygenerowane dynamicznie. W RCS Business Messaging karty rozszerzone obsługują tylko typy mediów graficznych i wideo, więc aby móc korzystać z zalet HTML do dynamicznego generowania treści, kod HTML musi najpierw zostać przekonwertowany na obraz.

Na szczęście większość współczesnych języków programowania obsługuje biblioteki wykonujące zrzuty ekranu stron internetowych lub komponentów, które potrafią generować co najmniej podstawowy kod HTML (np. JEditorPane), którego można użyć do wygenerowania obrazu.

Dostępne są też interfejsy API do robienia zdjęć stron internetowych. Na przykład interfejs Google Page Insights API może automatycznie generować zrzuty ekranu z adresu URL.

Przykład:

https://www.googleapis.com/pagespeedonline/v1/runPagespeed?url=https://www.google.com&screenshot=true

W poniższym przykładzie używamy aplikacji ekspresowej Node.js, aby wygenerować kartę pokładową użytkownika za pomocą kodu HTML, przekonwertować ją na obraz, przesłać na publicznie dostępny adres URL, a następnie załączyć na kartę informacyjną.

Tworzenie dynamicznej karty pokładowej

Aby rozpocząć, potrzebujemy kodu HTML, który posłuży do wygenerowania karty pokładowej, jak pokazano poniżej.

Przykład karty pokładowej

Możesz to zrobić na wiele sposobów, ale zdefiniujemy punkt końcowy adresu URL w aplikacji Node.js o nazwie /getTicket?msisdn=+12223334444, która renderuje kod HTML wymagany do korzystania z karty pokładowej za pomocą mechanizmu widoku EJS.

Załóżmy, że istnieje funkcja o nazwie getUserTicket, która pobiera numer telefonu użytkownika i zwraca obiekt biletu, który zawiera takie informacje jak czas wylotu, miejsce, typ biletu czy lokalizacja startowa.

W routerze ekspresowej definiujemy punkt końcowy getTicket, wywołujemy funkcję getUserTicket i przekazujemy zgłoszenie do szablonu EJS.

router.get('/getTicket', function(req, res, next) {
    // Get the passed in phone number
    let msisdn = req.body.msisdn;

    // Get the ticket object for this user
    let ticket = getUserTicket(msisdn);

    // Render the ticket in HTML using an EJS template
    res.render('ticket', {ticket: ticket});
});

Szablon EJS biletu określa poniższy kod HTML, aby wyrenderować przykładowe zgłoszenie Bonjour Rail.

<div>
  <div>
    <div class="left"><img width="200" src="/images/bonjour-rail-logo.png" /></div>
    <div class="right muted-text"><%= ticket.dateOfDeparture; %></div>
    <div class="cl"></div>
  </div>
  <div>
    <div class="left highlighted-text-color"><h2><%= ticket.startingLocation.city %></h2><br/><%= ticket.startingLocation.station %></div>
    <div class="right highlighted-text-color"><h2><%= ticket.endingLocation.city %></h2><br/><%= ticket.endingLocation.station %></div>
    <div class="cl"></div>
  </div>

  <div>
    <div class="left">
        <h3>PLATFORM <%= ticket.platform %></h3>
      <div>
        <div class="left">
          <div><h4>DEPART</h4></div>
          <div><%= ticket.departureTime %></div>
        </div>
        <div class="left">
          <div><h4>ARRIVE</h4></div>
          <div><%= ticket.arrivalTime %></div>
        </div>
        <div class="cl"></div>
      </div>
      <div>
        <div class="left">
          <div><h4>TICKET TYPE</h4></div>
          <div><%= ticket.ticketType %></div>
        </div>
        <div class="left">
          <div><h4>SEAT</h4></div>
          <div><%= ticket.seat %></div>
        </div>
        <div class="cl"></div>
      </div>
    </div>
    <div class="right">
      <img src="<%= ticket.qrCode %>" width="170" />
    </div>
    <div class="cl"></div>
  </div>
</div>

Tworzenie obrazu na podstawie kodu HTML

Zdefiniowaliśmy kod HTML do tworzenia karty pokładowej, ale potrzebujemy sposobu na przekonwertowanie jej na obraz.

Dostępnych jest wiele modułów open source o identyfikatorze Node.js do konwertowania nieprzetworzonego kodu HTML i adresów URL na obrazy. W tym przykładzie wykorzystamy node-webshot, czyli lekki kod towarzyszący PhantomJS.

PhantomJS to przeglądarka bez interfejsu graficznego, która może renderować kod HTML na obrazach. Ponieważ PhantomJS do renderowania korzysta ze środowiska WebKit, może obsługiwać złożone strony z obrazami, plikami CSS i JavaScriptem.

Po zainstalowaniu zrzutu ekranu węzła (npm install --save node-webshot) konwersja kodu HTML na obraz jest prosta.

var webshot = require('node-webshot');
let url = '/getTicket?msisdn=' + msisdn;
let htmlAsImageFileLocation = 'ticket.png';

// Define screenshot options
var options = {
      screenSize: {
            width: 550,
            height: 450
      },
      shotSize: {
            width: 550,
            height: 450
      },
      userAgent: 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.20 (KHTML, like Gecko) Mobile/7B298g'
    };

// Save html as an image
webshot(url, htmlAsImageFileLocation, options, function(err) {
  // TODO: Upload image to a publicly accessible URL
});

Przechowywanie plików pod publicznie dostępnym adresem URL

Aby korzystać z obrazu wygenerowanego za pomocą narzędzia webshot, potrzebujemy publicznie dostępnego adresu URL. Jeśli generujesz obraz na dedykowanym serwerze WWW, być może uda Ci się po prostu zapisać go w folderze publicznym, ale w tym przykładzie prześlesz go do Google Cloud Storage.

Poniższa funkcja pobiera lokalną lokalizację obrazu i przesyła ją do Google Cloud Storage, zwracając nowo utworzony link do multimediów.

function uploadImage(imageLocation) {
    const {Storage} = require('@google-cloud/storage');

    // Creates a client
    const storage = new Storage();

    // Define the Cloud storage location and file name
    const bucketName = 'sample-image-uploads';
    const yourFileDestination = 'uploaded-image.png';

    // Set the options for the upload to be readable by anyone
    const options = {
        destination: yourFileDestination,
        predefinedAcl: 'publicRead'
    };

    // Return a promise that includes the storage upload
    return new Promise(function(resolve, reject) {
        // Uploads a local file to the bucket
        storage.bucket(bucketName).upload(imageLocation, options)
            .then(results => {
                // Return the image URL
                resolve(results[0].metadata.mediaLink);
            }).catch(error => {
                reject(error);
            });
    });
}

Następnie musimy zastąpić skomentowany TODO wcześniej, wywołując wywołanie tej funkcji uploadImage.

// Save html as image
webshot(url, htmlAsImageFileLocation, options, function(err) {
      let uploadRequest = uploadImage(filename);

      uploadRequest.then(function(imageUrl) {
         // TODO: Use the imageUrl in a rich card to send to the user
      });
});

Wysyłanie karty informacyjnej z obrazem

Prawie Ci się udało! Wykonaj ostatni krok, definiując funkcję sendBoardingPass(imageUrl, msisdn), która tworzy kartę informacyjną RBM przy użyciu obrazu utworzonego w poprzednim kroku i wysyła ją do użytkownika.

Aby wysłać kartę informacyjną za pomocą RBM, używam tego samego pakietu SDK Node.js, który jest dostępny w przykładzie pierwszego agenta.

function sendBoardingPass(imageUrl, msisdn) {
    let title = 'Here is your boarding pass.';

    let suggestions = [
                {
                    reply: {
                        text: 'See more options',
                        postbackData: 'more_options',
                    }
                },
            ];

    let params = {
        messageText: title,
        msisdn: msisdn,
        imageUrl: imageUrl,
        suggestions: suggestions,
        height: 'TALL',
    };

    // Send the boarding pass
    rbmApiHelper.sendRichCard(params);
}

Poniżej znajdziesz zrzut ekranu z ostatecznym wynikiem.

Dynamiczny obraz na karcie informacyjnej

Podsumowanie i kierownik zespołu

Najprostszym sposobem na ulepszenie kart rozszerzonych jest wykorzystanie dynamicznego kodu HTML i przekształcenie go w obraz. Większość nowoczesnych języków programowania obsługuje biblioteki lub interfejsy API, które pomagają w realizacji konwersji. Czasem trzeba dopasować rozmiary obrazów, aby pasowały do konkretnego przypadku użycia. Jednak to świetny sposób na stworzenie atrakcyjniejszych treści wizualnych w agentach RBM.

Powodzenia i kodowania!