איך ליצור תמונות מ-HTML ליצירת כרטיסים דינמיים

סוג הכרטיס העשיר הוא אחד מסוגי התוכן החזקים והרב-תרבותיים ביותר ב-RCS Business Messaging. בעזרת צ'אט עשיר, אפשר לשלוח קטעים של מידע קשור בהודעה אחת, כולל תמונה או סרטון, כותרת, תיאור ועד עד ארבע הצעות לתשובות או לפעולות.

כרטיסים מתקדמים וקרוסלות בכרטיסים עשירים הם תכונות יעילות שיכולות לעזור לכם ליצור חוויות מעניינות למשתמשים. הן פועלות כל עוד התמונות שאתם צריכים לשתף הן תמונות סטטיות, כמו שובר או מוצר. אבל מה קורה אם צריך לשלוח תוכן דינמי המבוסס על מידע על המשתמש, כמו כרטיס עלייה למטוס?

במאמר הזה אראה לכם איך ליצור תמונות במהירות באמצעות HTML ומטמיעים את התמונות האלה בכרטיסי התצוגה העשירה שהנציג שולח. נתחיל בדיון על המרת HTML לתמונה.

מ-HTML לתמונה

HTML הוא כלי מעולה לפריסת שילובים של טקסט ומדיה. כמפתחים, אם נצטרך לבנות מוצר כדי לשלוח למשתמש משהו כמו כרטיס עלייה למטוס, תרשים שימוש בנתונים או כל סוג אחר של מידע ספציפי למשתמש, סביר להניח ש-HTML שנוצר באופן דינמי הוא הכלי שבו נשתמש. ב-RCS Business Messaging, כרטיסי מדיה עשירה תומכים רק בסוגי מדיה של וידאו ותמונות, כך שכדי למנף את כוח ה-HTML ליצירת תוכן דינמי צריך קודם להמיר את ה-HTML לתמונה.

לכן, רוב שפות התכנות המודרניות תומכות בספריות ליצירת צילומי מסך של דפי אינטרנט או רכיבים שיכולים לעבד HTML בסיסי לפחות (למשל JEditorPane), שבו אפשר להשתמש כדי ליצור תמונה.

יש גם ממשקי API זמינים לצילום תמונות של דפי אינטרנט. לדוגמה, Google Page Insights API של Google יכול ליצור באופן אוטומטי צילומי מסך מכתובת URL.

דוגמה:

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

בשלבים הבאים, נשתמש באפליקציה Express של Node.js כדי ליצור כרטיס עלייה למטוס ספציפי למשתמש באמצעות HTML, להמיר אותו לתמונה, להעלות אותו לכתובת URL שנגישה לכולם, ולאחר מכן לצרף את התמונה בכרטיס עשיר כדי לשלוח אותה למשתמש.

יצירת כרטיס עלייה למטוס דינמי

כדי להתחיל, אנחנו צריכים את קוד ה-HTML כדי ליצור כרטיס עלייה למטוס כמו בתמונה למטה.

דוגמה לכרטיס עלייה למטוס

יש הרבה דרכים להשיג את המטרה הזו, אבל אנחנו עומדים להגדיר נקודת קצה לכתובת URL באפליקציית Node.js בשם /getTicket?msisdn=+12223334444. זהו עיבוד של ה-HTML שנחוץ לכרטיס העלייה למטוס באמצעות מנוע התצוגה של EJS.

נניח שיש פונקציה בשם getUserTicket שלוקחת את מספר הטלפון של המשתמש ומחזירה אובייקט כרטיס שמכיל מידע כמו שעת יציאה, מושב, סוג כרטיס, מיקום התחלה וכו'.

בנתב של האפליקציה Express, אנחנו מגדירים את נקודת הקצה getTicket, מבצעים קריאה לפונקציה getUserTicket ומעבירים את הכרטיס לתבנית 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});
});

תבנית ה-EJS של הכרטיס מגדירה את קוד ה-HTML הבא לצורך עיבוד הכרטיס לדוגמה של 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>

יצירת תמונה מ-HTML

הגדרנו את ה-HTML כדי לבנות את כרטיס העלייה למטוס, אבל אנחנו צריכים דרך להמיר אותו לתמונה.

יש מודולים רבים של קוד פתוח מסוג Node.js שזמינים להמרת תמונות גם מ-HTML וגם מכתובות URL גולמיות. לצורך דוגמה זו, נשתמש ב-node-webshot, שהוא wrapper קל סביב PhantomJS.

PHantomJS הוא דפדפן ללא סקריפטים, שיכול לעבד HTML בתמונות. מאחר ש-PantomJS מסתמך על WebKit לעיבוד, הוא יכול לטפל בדפים מורכבים עם תמונות, CSS ו-JavaScript.

לאחר ההתקנה של צילום מסך מצומת (npm install --save node-webshot), קל להמיר HTML לתמונה.

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
});

אחסון קבצים בכתובת URL נגישה לכולם

כדי להשתמש בתמונה שנוצרה מצילום אינטרנט, אנחנו צריכים כתובת URL שנגישה לכולם. אם אתם יוצרים את התמונה בשרת אינטרנט ייעודי, ייתכן שתוכלו לשמור את הקובץ בתיקייה ציבורית. עם זאת, בדוגמה הזו, נעלה את הקובץ ל-Google Cloud Storage.

הפונקציה שלמטה מקבלת מיקום תמונה מקומי ומעלה אותו ל-Google Cloud Storage, ומחזירה את קישור המדיה החדש שנוצר.

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);
            });
    });
}

בשלב הבא עלינו להחליף את TODO מהתגובה הקודמת, בקריאה לשימוש בפונקציה הזו של 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
      });
});

שליחת כרטיס עשיר עם התמונה

כמעט סיימנו. בואו משלימים את השלב האחרון על ידי הגדרת הפונקציה sendBoardingPass(imageUrl, msisdn), שיוצרת כרטיס Rich RBM באמצעות התמונה שנוצרה בשלב הקודם ושולחת אותו למשתמש.

כדי לשלוח את כרטיס ה-rich with RBM, נעשה שימוש באותה SDK מסוג Node.js שזמין בדוגמה הראשונה לסוכן.

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);
}

לפניכם צילום מסך של התוצאה הסופית.

תמונה דינמית בכרטיס עשיר

סיכום ו-TL;DR

הדרך הפשוטה ביותר להפוך כרטיסים עשירים לגמישים יותר היא למנף את ה-HTML הדינמי ולהמיר את ה-HTML לתמונות. רוב שפות התכנות המודרניות תומכות בספריות או בממשקי API שיעזרו לך להשלים את ההמרה. ייתכן שתצטרכו לנסות את גודל התמונה כדי להתאים אותה לתרחיש לדוגמה שלכם, אבל זוהי דרך מצוינת ליצור רכיבים חזותיים מושכים יותר בסוכני RBM.

שיהיה בהצלחה!