|
|
|
import axios from "axios";
|
|
|
|
import express, { json } from "express";
|
|
|
|
import Queue from "bull";
|
|
|
|
import Bottleneck from "bottleneck";
|
|
|
|
|
|
|
|
const app = express();
|
|
|
|
app.use(json());
|
|
|
|
|
|
|
|
const requestQueue = new Queue("request-queue", {
|
|
|
|
redis: {
|
|
|
|
host: "127.0.0.1",
|
|
|
|
port: 6379,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const limiter = new Bottleneck({
|
|
|
|
maxConcurrent: 1,
|
|
|
|
minTime: 1,
|
|
|
|
});
|
|
|
|
|
|
|
|
async function sendRequest(data) {
|
|
|
|
const botToken = data.botToken;
|
|
|
|
const chat_id = data.chat_id;
|
|
|
|
const text = data.text;
|
|
|
|
try {
|
|
|
|
const response = await axios.post(
|
|
|
|
`https://api.telegram.org/bot${botToken}/sendMessage`,
|
|
|
|
{
|
|
|
|
chat_id: chat_id,
|
|
|
|
text: text,
|
|
|
|
}
|
|
|
|
);
|
|
|
|
console.log(response.data);
|
|
|
|
} catch (error) {
|
|
|
|
console.error(
|
|
|
|
"Error:",
|
|
|
|
error.response ? error.response.data : error.message
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
requestQueue.process(async (job) => {
|
|
|
|
try {
|
|
|
|
await limiter.schedule(() => sendRequest(job.data));
|
|
|
|
} catch (error) {
|
|
|
|
throw new Error(`Request failed: ${error.message}`);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
requestQueue.on("completed", (job) => {
|
|
|
|
// job.remove()
|
|
|
|
console.log(`Job ${job.id} completed successfully.`);
|
|
|
|
});
|
|
|
|
|
|
|
|
requestQueue.on("failed", (job, error) => {
|
|
|
|
console.log(`Job ${job.id} failed with error: ${error.message}`);
|
|
|
|
if (job.attemptsMade < 3) {
|
|
|
|
job.retry();
|
|
|
|
} else {
|
|
|
|
console.error(
|
|
|
|
`Job ${job.id} moved to dead-letter queue after ${job.attemptsMade} attempts`
|
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
app.get("/bot:token/*", async (req, res) => {
|
|
|
|
const url = req.url;
|
|
|
|
const botTokenEndIndex = url.indexOf("/", 1);
|
|
|
|
const botToken = url.substring(4, botTokenEndIndex);
|
|
|
|
|
|
|
|
const queryParams = req.query;
|
|
|
|
|
|
|
|
const data = {
|
|
|
|
botToken: botToken,
|
|
|
|
chat_id: queryParams.chat_id,
|
|
|
|
text: queryParams.text,
|
|
|
|
};
|
|
|
|
try {
|
|
|
|
const job = await requestQueue.add(data, {
|
|
|
|
attempts: 3,
|
|
|
|
backoff: 5000,
|
|
|
|
removeOnComplete: true,
|
|
|
|
});
|
|
|
|
res.status(202).send({ jobId: job.id });
|
|
|
|
} catch (error) {
|
|
|
|
res.status(500).send({ error: error.message });
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
app.post("/bot:token/*", async (req, res) => {
|
|
|
|
const url = req.url;
|
|
|
|
const botTokenEndIndex = url.indexOf("/", 1);
|
|
|
|
const botToken = url.substring(4, botTokenEndIndex);
|
|
|
|
|
|
|
|
const body = req.body;
|
|
|
|
const data = {
|
|
|
|
botToken: botToken,
|
|
|
|
chat_id: body.chat_id,
|
|
|
|
text: body.text,
|
|
|
|
};
|
|
|
|
try {
|
|
|
|
const job = await requestQueue.add(data, {
|
|
|
|
attempts: 3,
|
|
|
|
backoff: 5000,
|
|
|
|
removeOnComplete: true,
|
|
|
|
});
|
|
|
|
res.status(202).send({ jobId: job.id });
|
|
|
|
} catch (error) {
|
|
|
|
res.status(500).send({ error: error.message });
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
app.listen(3000, () => {
|
|
|
|
console.log("Microservice listening on port 3000");
|
|
|
|
});
|