Aller au contenu principal

Express.js Integration

Intégrez YODI dans une application Express.js complète.

Installation

npm init -y
npm install express axios dotenv cors body-parser

Application Express Complète

app.js

const express = require("express");
const cors = require("cors");
const bodyParser = require("body-parser");
require("dotenv").config();

const app = express();

// Middleware
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

// Routes
const translationRoutes = require("./routes/translation");
const analysisRoutes = require("./routes/analysis");
const communicationRoutes = require("./routes/communication");
const subscriptionRoutes = require("./routes/subscription");

app.use("/api/translate", translationRoutes);
app.use("/api/analyze", analysisRoutes);
app.use("/api/communication", communicationRoutes);
app.use("/api/subscription", subscriptionRoutes);

// Health check
app.get("/health", (req, res) => {
res.json({ status: "ok", service: "YODI API Wrapper" });
});

// Error handling
app.use((err, req, res, next) => {
console.error(" Erreur:", err);
res.status(err.status || 500).json({
error: err.message,
status: err.status || 500,
});
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(` Serveur démarré sur http://localhost:${PORT}`);
});

module.exports = app;

config/yodi.js

const axios = require("axios");
require("dotenv").config();

const yodiClient = axios.create({
baseURL: process.env.YODI_BASE_URL || "https://admin.yodi.tg/api",
headers: {
Authorization: `Bearer ${process.env.YODI_API_KEY}`,
"Content-Type": "application/json",
},
timeout: 10000,
});

// Interceptor pour les erreurs
yodiClient.interceptors.response.use(
(response) => response,
(error) => {
if (error.response?.status === 429) {
console.warn(" Rate limited - implementing backoff");
}
return Promise.reject(error);
},
);

module.exports = yodiClient;

routes/translation.js

const express = require("express");
const router = express.Router();
const yodiClient = require("../config/yodi");

// POST /api/translate
router.post("/", async (req, res, next) => {
try {
const { text, targetLanguage, sourceLanguage } = req.body;

if (!text || !targetLanguage) {
return res.status(400).json({
error: "text et targetLanguage sont requis",
});
}

const response = await yodiClient.post("/ai/translate", {
text,
targetLanguage,
sourceLanguage,
});

res.json({
success: true,
data: response.data.data,
});
} catch (error) {
next(error);
}
});

// POST /api/translate/batch
router.post("/batch", async (req, res, next) => {
try {
const { texts, targetLanguage } = req.body;

if (!Array.isArray(texts) || !targetLanguage) {
return res.status(400).json({
error: "texts (array) et targetLanguage sont requis",
});
}

const results = [];

for (const text of texts) {
try {
const response = await yodiClient.post("/ai/translate", {
text,
targetLanguage,
});

results.push({
original: text,
translated: response.data.data.translated,
status: "success",
});
} catch (error) {
results.push({
original: text,
status: "failed",
error: error.message,
});
}
}

res.json({
success: true,
count: results.length,
results,
});
} catch (error) {
next(error);
}
});

module.exports = router;

routes/analysis.js

const express = require("express");
const router = express.Router();
const yodiClient = require("../config/yodi");

// POST /api/analyze
router.post("/", async (req, res, next) => {
try {
const { text } = req.body;

if (!text) {
return res.status(400).json({ error: "text est requis" });
}

const response = await yodiClient.post("/ai/analyze", { text });

res.json({
success: true,
data: response.data.data,
});
} catch (error) {
next(error);
}
});

// POST /api/analyze/sentiment
router.post("/sentiment", async (req, res, next) => {
try {
const { text } = req.body;

if (!text) {
return res.status(400).json({ error: "text est requis" });
}

const response = await yodiClient.post("/ai/analyze", { text });
const { sentiment } = response.data.data;

res.json({
success: true,
sentiment: {
label: sentiment.label,
confidence: sentiment.confidence,
percentage: Math.round(sentiment.confidence * 100),
},
});
} catch (error) {
next(error);
}
});

module.exports = router;

routes/communication.js

const express = require("express");
const router = express.Router();
const yodiClient = require("../config/yodi");

// POST /api/communication/sms
router.post("/sms", async (req, res, next) => {
try {
const { phone, input } = req.body;

if (!phone || !input) {
return res.status(400).json({
error: "phone et input sont requis",
});
}

const response = await yodiClient.post("/ai/sms/communication", {
phone,
input,
});

res.json({
success: true,
messageId: response.data.data.messageId,
});
} catch (error) {
next(error);
}
});

// POST /api/communication/call (Voice Call)
router.post("/call", async (req, res, next) => {
try {
const { phone, input } = req.body;

if (!phone || !input) {
return res.status(400).json({
error: "phone et input sont requis",
});
}

const response = await yodiClient.post("/ai/call/communication", {
phone,
input,
});

res.json({
success: true,
messageId: response.data.data.messageId,
});
} catch (error) {
next(error);
}
});

module.exports = router;

routes/subscription.js

const express = require("express");
const router = express.Router();
const yodiClient = require("../config/yodi");

// GET /api/subscription/plans
router.get("/plans", async (req, res, next) => {
try {
const response = await yodiClient.get("/subscription/plans");

res.json({
success: true,
plans: response.data.data,
});
} catch (error) {
next(error);
}
});

// GET /api/subscription/current
router.get("/current", async (req, res, next) => {
try {
const response = await yodiClient.get("/subscription/current");

res.json({
success: true,
subscription: response.data.data,
});
} catch (error) {
next(error);
}
});

module.exports = router;

Middleware Custom

middleware/auth.js

const authMiddleware = (req, res, next) => {
const apiKey = req.headers["x-api-key"];

if (!apiKey || apiKey !== process.env.APP_API_KEY) {
return res.status(401).json({ error: "API Key manquante ou invalide" });
}

next();
};

module.exports = authMiddleware;

Utilisez dans vos routes:

const authMiddleware = require("../middleware/auth");

router.post("/", authMiddleware, async (req, res) => {
// Votre logique...
});

middleware/rateLimit.js

const rateLimit = require("express-rate-limit");

const limiter = rateLimit({
windowMs: 60 * 1000, // 1 minute
max: 100, // Limite 100 requêtes par minute
message: "Trop de requêtes, veuillez réessayer plus tard",
standardHeaders: true,
legacyHeaders: false,
});

module.exports = limiter;

Utilisez dans app.js:

const rateLimit = require("./middleware/rateLimit");
app.use(rateLimit);

Tests avec Postman/cURL

Translation

curl -X POST http://localhost:3000/api/translate \
-H "Content-Type: application/json" \
-d '{
"text": "Hello world",
"targetLanguage": "fr"
}'

Analysis

curl -X POST http://localhost:3000/api/analyze/sentiment \
-H "Content-Type: application/json" \
-d '{
"text": "I love this service!"
}'

Send SMS

curl -X POST http://localhost:3000/api/communication/sms \
-H "Content-Type: application/json" \
-d '{
"phone": "+22890123456",
"input": "Bienvenue sur YODI!"
}'

Structure du Projet

yodi-api-wrapper/
├── app.js
├── package.json
├── .env
├── config/
│ └── yodi.js
├── routes/
│ ├── translation.js
│ ├── analysis.js
│ ├── communication.js
│ └── subscription.js
├── middleware/
│ ├── auth.js
│ └── rateLimit.js
└── models/
└── (optionnel: base de données)

Déploiement

Heroku

heroku create your-app-name
git push heroku main
heroku config:set YODI_API_KEY=your_key

Docker

Créez Dockerfile:

FROM node:18-alpine

WORKDIR /app
COPY package*.json ./
RUN npm install

COPY . .

EXPOSE 3000
CMD ["node", "app.js"]

Créez docker-compose.yml:

version: "3.8"
services:
app:
build: .
ports:
- "3000:3000"
environment:
- YODI_API_KEY=${YODI_API_KEY}
- NODE_ENV=production

Lancez:

docker-compose up

Exemple Complet: Platform de Support Client

// supportApp.js
const express = require("express");
const yodiClient = require("./config/yodi");

const app = express();
app.use(express.json());

class SupportPlatform {
async createTicket(customerData, issue) {
// 1. Analyser le problème
const analysis = await yodiClient.post("/ai/analyze", {
text: issue,
});

const { sentiment, confidence } = analysis.data.data;
const priority = sentiment === "negative" ? "high" : "normal";

// 2. Notifier le support team par SMS
await yodiClient.post("/ai/sms/communication", {
phone: process.env.SUPPORT_PHONE,
input: `Nouveau ticket ${priority}: ${issue.substring(0, 50)}`,
});

return {
ticketId: Math.random().toString(36).substr(2, 9),
priority,
sentiment,
};
}

async respondToTicket(ticketId, response) {
// Traduire la réponse automatiquement
const translated = await yodiClient.post("/ai/translate", {
text: response,
targetLanguage: "fr",
});

return translated.data.data.translatedText;
}
}

// Routes
const platform = new SupportPlatform();

app.post("/tickets", async (req, res) => {
try {
const ticket = await platform.createTicket(
req.body.customer,
req.body.issue,
);
res.json({ success: true, ticket });
} catch (error) {
res.status(500).json({ error: error.message });
}
});

app.post("/tickets/:id/respond", async (req, res) => {
try {
const response = await platform.respondToTicket(
req.params.id,
req.body.response,
);
res.json({ success: true, response });
} catch (error) {
res.status(500).json({ error: error.message });
}
});

app.listen(3000, () => {
console.log(" Support Platform sur http://localhost:3000");
});

Ressources