
Erstellen einer App zur Erinnerung an WhatsApp-Ereignisse
Lesedauer: 6 Minuten
Einführung
In diesem Tutorial lernen wir, eine WhatsApp-Konversation zur Erinnerung an Ereignisse einzurichten, mit der Sie täglich Nachrichten mit den Ereignissen von heute erhalten, um sich an zukünftige Ereignisse zu erinnern und diese abzufragen. Wir werden eine WhatsApp-Sandbox für ein- und ausgehende Nachrichten einrichten und Ereignisse aus einer Firebase Firestore-Datenbankinstanz abrufen.
Sie finden den Code für dieses Projekt auf GitHub.
Voraussetzungen
Ein Texteditor oder eine IDE
Knotenpunkt und npm installiert
Skizze des Projekts
Am Ende dieses Projekts sollte Ihr Projektordner so aussehen:
[node_modules]
.env
index.js
package-lock.json
package.json
events-reminder-store-credentials.json Erstellen Sie ein Node-Projekt und fügen Sie die Abhängigkeiten hinzu
Initialisieren Sie in Ihrem neu erstellten Projektverzeichnis ein neues Knotenprojekt. Dadurch wird eine neue package.json Datei. Die -y Flagge füllt automatisch die Standardwerte aus, ohne nach den Details zu fragen.
npm init -yUnd installieren Sie die folgenden Abhängigkeiten für unser Projekt. Alternativ können Sie auch das Projekt von GitHub klonen klonen und die Abhängigkeiten installieren.
npm install axios dotenv express node-cronDiese Abhängigkeiten sind in unserem Projekt wichtig, um HTTP-Anfragen an externe Dienste zu stellen und zu bearbeiten, Umgebungsvariablen zu verwalten, unseren Server einzurichten und die täglichen Nachrichten mit den Ereignissen zu planen.
Erstellen einer WhatsApp-Sandbox
Wir verwenden die WhatsApp-Sandkasten für dieses Tutorial, aber Sie können auch Ihren geschäftlichen WhatsApp Account integrieren.
Verwendung der Sandbox
Mit der Messages API Sandbox können Sie Testnachrichten auf unterstützten Messaging-Plattformen wie folgt versenden:
Umgebungsvariablen
Erstellen Sie eine .env Datei für Ihr Projekt und fügen Sie die Umgebungsvariablen hinzu, die Sie im folgenden Codefragment finden.
VONAGE_API_KEY=
VONAGE_API_SECRET=
VONAGE_WHATSAPP_NUMBER=
TO_NUMBER=Michaels Blogbeitrag bietet eine wunderbare Erklärung der Verwendung von Umgebungsvariablen in Node.js.
Die VONAGE_API_KEY und VONAGE_API_SECRET finden Sie auf dem Dashboard von Vonage.
Vonage DashboardDie VONAGE_WHATSAPP_NUMBER finden Sie am Ende der Messages API Sandbox-Seite.
TO_NUMBER ist die Nummer, von der aus Sie eine Nachricht an die WhatsApp-Sandbox senden werden.
HINWEIS: Verwenden Sie keine führenden
+oder00wenn Sie eine Telefonnummer eingeben, beginnen Sie mit der Landesvorwahl, z. B. 16600800000.
Senden einer WhatsApp-Nachricht
Sobald wir die Messages API Sandbox-Seiteöffnet, zeigt ein cURL-Befehl, wie man einen Endpunkt hinzufügt und dann eine WhatsApp-Nummer unten auf der Seite mitteilt. Ich habe diesen Code genommen und ihn in Node.js umgesetzt.
//index.js
require("dotenv").config();
const user = process.env.VONAGE_API_KEY;
const password = process.env.VONAGE_API_SECRET;
const from_number = process.env.VONAGE_WHATSAPP_NUMBER;
const to_number = process.env.VONAGE_TO_NUMBER;
const data = JSON.stringify({
from: { type: "whatsapp", number: from_number },
to: { type: "whatsapp", number: to_number },
message: {
content: {
type: "text",
text: "The events we have today are: event",
},
},
});
const https = require("https");
const options = {
hostname: "messages-sandbox.nexmo.com",
port: 443,
path: "/v0.1/messages",
method: "POST",
authorization: {
username: user,
password: password,
},
headers: {
Authorization: "Basic " + btoa(`${user}:${password}`),
"Content-Type": "application/json",
},
};
const req = https.request(options, (res) => {
console.log(`statusCode: ${res.statusCode}`);
res.on("data", (d) => {
process.stdout.write(d);
});
});
req.on("error", (e) => {
console.error(e);
});
req.write(data);
req.end();In dieser einfachen Form erhalte ich jedes Mal, wenn ich die von mir erstellte Datei ausführe, eine Nachricht zurück, die den Inhalt der Variablen enthält text. Dieser Blogeintrag zeigt ein Beispiel für die Verwendung der WhatsApp-Sandbox für eingehende Nachrichten. Da wir aber wollen, dass unsere Ereignisse uns daran erinnern, werden wir für das Beispiel dieses Tutorials eine ausgehende Nutzung verwenden.
Erzeugen Sie eine localtunnel.me URL mit dem Befehlscode: lt --port 8000, fügen Sie die generierte URL ein und hängen Sie /inbound und /eventan und klicken Sie auf "Webhaken speichern".
Jetzt schalten wir um; die WhatsApp-Sandbox antwortet, sobald der Benutzer eine Nachricht sendet. Lassen Sie uns antworten: "Die Ereignisse, die wir heute haben, sind: Ereignisse", sobald der Benutzer eine Nachricht sendet. Aber es werden noch keine Ereignisse ausgewählt; wir senden einfach diese Textzeichenfolge. Bis hierher haben Sie also gesehen, wie wir eine WhatsApp empfangen, sobald wir die Datei ausführen, und wie wir eine ausgehende Antwort erhalten. Gehen wir nun zum nächsten Schritt über, bei dem wir tatsächlich Ereignisse aus einer Datenbank abrufen werden.
//index.js
require("dotenv").config();
const express = require("express");
const https = require("https");
const app = express();
app.use(express.json());
const PORT = 8000;
const from_number = process.env.VONAGE_WHATSAPP_NUMBER; // Your Vonage WhatsApp number
app.post("/inbound", (req, res) => {
console.log("Inbound message received:", req.body);
// Assuming the structure of req.body is as expected
const to_number = req.body.from.number; // Sender's number to which you're replying
console.log({to_number});
const data = JSON.stringify({
from: { type: "whatsapp", number: from_number },
to: { type: "whatsapp", number: process.env.TO_NUMBER },
message: {
content: {
type: "text",
text: "The events we have today are: events",
},
},
});
const options = {
hostname: "messages-sandbox.nexmo.com",
port: 443,
path: "/v0.1/messages",
method: "POST",
headers: {
Authorization:
"Basic " +
Buffer.from(
${process.env.VONAGE_API_KEY}:${process.env.VONAGE_API_SECRET}
).toString("base64"),
"Content-Type": "application/json",
"Content-Length": Buffer.byteLength(data),
},
};
const reqOut = https.request(options, (resOut) => {
console.log(`statusCode: ${resOut.statusCode}`);
resOut.on("data", (d) => {
process.stdout.write(d);
});
});
reqOut.on("error", (e) => {
console.error(e);
});
reqOut.write(data);
reqOut.end();
res.status(200).send("Inbound message processed");
});
app.listen(PORT, () => {
console.log(`Server is listening on port ${PORT}`);
}); Firebase
Wie zu Beginn dieses Tutorials erwähnt, benötigen Sie ein Firebase Account. Melden Sie sich bei Ihrem Firebase Account an, erstellen Sie ein Firebase Projekt, legen Sie den Standort fest und ein Abrechnungskonto erstellen.
Firestore
Erstellen Sie eine neue Firestore-Datenbankinstanz. Sie müssen außerdem einen Service Account erstellen und fügen Sie die JSON-Datei zu Ihrem Node-Projekt hinzu.
Sie müssen eine Sammlung. Füllen Sie die Firestore-Felder mit den Ereignissen. Erstellen Sie jeden Ereignisknoten, der drei Felder enthalten sollte: date, vom Typ Zeitstempel; details; und event_type, beide vom Typ String.
Hinzufügen des Codes
Dieser Codeblock zeigt, wie Sie das Firebase Admin SDK importieren, die Firebase-App initialisieren, Ihr Servicekonto aus einer lokalen JSON-Datei laden und auf Ihre Firestore-Datenbank zugreifen.
const admin = require("firebase-admin");
admin.initializeApp({
credential: admin.credential.cert(
require("./events-reminder-store-credentials.json")
),
});
const db = admin.firestore(); Erstellen der Funktion zum Abrufen der heutigen Ereignisse
Diese Funktion initialisiert einen Datumsbereich für den aktuellen Tag, der von Mitternacht bis kurz vor Mitternacht des nächsten Tages reicht. Sie sucht dann in Firestore nach Dokumenten in der Ereignissammlung, bei denen das Datumsfeld in diesen Bereich fällt. Wenn Dokumente gefunden werden, wird eine Zeichenfolge erstellt, die die Ereignisse des Tages zusammenfasst.
async function getEventsForToday() {
const today = new Date();
today.setHours(0, 0, 0, 0); // Set the time to the start of the day (midnight)
const tomorrow = new Date(today);
tomorrow.setDate(today.getDate() + 1); // Set to the start of the next day (midnight next day)
try {
// Query Firestore for events within today's date range
const snapshot = await db.collection('events')
.where('date', '>=', admin.firestore.Timestamp.fromDate(today))
.where('date', '<', admin.firestore.Timestamp.fromDate(tomorrow))
.get();
if (snapshot.empty) {
return 'No events found for today.'; // Return message if no events are found
}
let eventsText = 'Today\'s events: ';
snapshot.forEach(doc => {
const event = doc.data();
eventsText += ${event.details}; ; // Concatenate each event detail into a string
});
return eventsText; // Return the string of today's events
} catch (error) {
console.error("Error fetching events:", error);
return "Failed to fetch events."; // Handle errors in fetching data
}
}Die gleiche getEventsForToday Funktion prüft die Ereignisse des heutigen Tages wie oben beschrieben. Sie stellt das Datum so ein, dass alle Ereignisse vom Beginn bis zum Ende des aktuellen Tages abgedeckt sind, d. h., sie holt die für heute geplanten Ereignisse.
async function handleDateRequest(dateString, requesterNumber) {
const queryDate = new Date(dateString + 'T00:00:00Z'); // Set the query date start
const queryDateEnd = new Date(queryDate);
queryDateEnd.setDate(queryDate.getDate() + 1); // Set the query date end to the next day
try {
const snapshot = await db.collection('events')
.where('date', '>=', admin.firestore.Timestamp.fromDate(queryDate))
.where('date', '<', admin.firestore.Timestamp.fromDate(queryDateEnd))
.get();
if (snapshot.empty) {
sendMessage('No events found for ' + dateString, requesterNumber); // Inform no events found
return;
}
let eventsText = Events on ${dateString}: ;
snapshot.forEach(doc => {
const event = doc.data();
eventsText += ${event.details}; ; // Aggregate event details
});
sendMessage(eventsText, requesterNumber); // Send the aggregated event details
} catch (error) {
console.error("Error retrieving events:", error);
}
}Der Code verwendet admin.firestore.Timestamp.fromDate() zur Konvertierung von JavaScript Date Objekte in Firestore-kompatible Zeitstempelformate. Dies ist wichtig für die genaue Abfrage von in Firestore gespeicherten Datumsfeldern.
Alle Firestore-Interaktionen enthalten try-catch-Blöcke, um Fehler effektiv zu behandeln und zu protokollieren, so dass alle Probleme während der Datenbankoperationen abgefangen werden und diagnostiziert werden können.
Künftige Nachrichten planen
Wir könnten eine Cloud-Funktion planen planen und sie mit Cloud-Funktionen bereitstellen. Für dieses Tutorial werden wir jedoch node-cron. Ich habe ihn so eingestellt, dass er täglich um 09:50 Uhr in der Zeitzone "Europa/London" Nachrichten sendet, aber Sie können es auf eine Zeit und Zeitzone einstellen, die für Sie mehr Sinn macht.
const cron = require("node-cron");
cron.schedule("50 09 *", async () => {
console.log("Running a job at 09:50 at Europe/London timezone");
const eventsText = await getEventsForToday();
sendMessage(eventsText, TO_NUMBER);
}, {
scheduled: true,
timezone: "Europe/London",
}); Bonus: Maßgeschneiderte Nachrichten mit Open AI hinzufügen
Heutzutage sind viele von uns begeistert von der Verwendung von LLMs (Large Language Models). Wie wäre es, wenn Sie für diese Ereignisse, an die Sie erinnert werden sollen, personalisierte Nachrichten versenden könnten? Sie können API-Aufrufe an OpenAI tätigen, um eine personalisierte Ereignismeldung für Sie zu generieren - Sie können sie dann kopieren und einfügen und verwenden!
Installieren Sie die npm-Abhängigkeit von OpenAI über Ihr Terminal.
npm install openai
Importieren Sie die Abhängigkeit in Ihre JavaScript-Datei.
const OpenAI = require("openai");
Generieren Sie einen API-Schlüssel und richten Sie den OpenAI-Client ein.
const openai = new OpenAI({ apiKey: OPENAI_API_KEY });
Fügen Sie die OPENAI_API_KEY zu Ihrer .env-Datei hinzu.
OPENAI_API_KEY=
Erstellen Sie eine generateCreativeMessage() Funktion, die die API von OpenAI verwendet, um auf der Grundlage der eingegebenen Ereignisinformationen benutzerdefinierten Text zu erzeugen. Die Funktion sendet eine Anfrage an die API und bittet sie, Text auf der Grundlage einer Eingabeaufforderung zu erstellen, die Ereignisdetails enthält. Die Funktion gibt eine maximale Wortanzahl für die Antwort vor. Ist die Anfrage erfolgreich, wird der erzeugte Text gekürzt und zurückgegeben. Tritt ein Fehler auf, gibt eine Fallback-Meldung die Ereignisdetails wieder.
async function generateCreativeMessage(eventsText) {
try {
const response = await openai.completions.create({
model: "gpt-3.5-turbo-instruct",
prompt: Create a friendly and engaging message based on the following events: ${eventsText},
max_tokens: 150,
});
return response.choices[0].text.trim();
} catch (error) {
console.error("Failed to generate message with OpenAI:", error);
return Here's what's happening today: ${eventsText}; // Fallback text
}
}Und vergessen wir nicht, die geplante Nachricht zu aktualisieren und die Funktion generateCreativeMessage() Funktion hinzuzufügen, um eine maßgeschneiderte Nachricht auf der Grundlage der Ereignisse zu erstellen. Die ursprünglichen Ereignisdetails und die neu erstellte Nachricht werden an eine bestimmte Telefonnummer gesendet. sendMessage() Funktion.
cron.schedule(
"50 09 *",
async () => {
console.log("Running a job at 09:50 at Europe/London timezone");
const eventsText = await getEventsForToday();
const creativeText = await generateCreativeMessage(eventsText);
sendMessage(
${eventsText}\n\nSuggested message to send: ${creativeText},
TO_NUMBER
);
},
{
scheduled: true,
timezone: "Europe/London",
}
);
Hinweis: Beachten Sie die API-Kosten, die API-Tarifbeschränkungen und den Datenschutz, wenn Sie die API von OpenAI nutzen.
Die Anwendung ausführen
Die Anwendung prüft jeden Tag zu einer bestimmten Zeit, welche Ereignisse heute anstehen, und sendet eine Nachricht über WhatsApp. Sie können nach Ereignissen an bestimmten Tagen suchen, indem Sie Nachrichten im Format "Ereignisse am JJJJ-MM-TT" über WhatsApp senden.
Führen Sie den Befehl lt aus, um den Tunnel zu starten.
lt --port 8000
Fügen Sie die generierte URL zu Ihrer Messages API Sandbox Webhooks, und vergessen Sie nicht, auf Webhooks speichern zu klicken.
Messages API WebhooksFühren Sie die von Ihnen erstellte JavaScript-Datei auf demselben Port aus, auf den der Tunnel hört.
node index.js
Sie können die node.cron Funktion aktualisieren, um zu einem beliebigen Zeitpunkt eine Nachricht zu senden, und Sie können auch eine Nachricht an die WhatsApp-Sandbox-Nummer senden, um nach den heutigen Ereignissen im Format zu fragen.
Mögliche Erweiterung - Vonage AI Studio
Wir haben dies mit der Messages API von Vonage erreicht, aber Sie hätten auch Vonage AI Studio verwenden können, um die Konversation zu gestalten und Ihr Backend zu integrieren. Es gibt sogar ein Add-on Gen AI Node, mit dem Sie die Leistung des Large Language Model von OpenAI nutzen können, um Ihren virtuellen Assistenten so zu dynamisieren, dass er Ihre Benutzeranfragen mit dem Wissen um kontextspezifische Nuancen und dem Vorteil, das Internet als Datenquelle zu haben, bearbeitet. Hier ist ein Tutorial für Aufbau eines FAQ-Antwortdienstes mit OpenAI und Vonage AI Studio.
Schlussfolgerung
Heute haben Sie gesehen, wie Sie die Vonage Messages API Sandbox integriert mit Firebase Firestore und Cloud Functions for Firestore verwenden können, um Erinnerungsnachrichten zu empfangen. Schließen Sie sich uns auf unserem Vonage Community Slack oder senden Sie uns eine Nachricht auf X, früher bekannt als Twitter.