Skip to content

Commit

Permalink
add sendTelegramDocument function
Browse files Browse the repository at this point in the history
add deleteTelegramMessage function
  • Loading branch information
TimurRin committed Jul 24, 2024
1 parent 78a5308 commit 0cf2253
Show file tree
Hide file tree
Showing 4 changed files with 227 additions and 76 deletions.
8 changes: 6 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { sendTelegramMessage } from "./stateless.js";
import {
deleteTelegramMessage,
sendTelegramDocument,
sendTelegramMessage,
} from "./stateless.js";

export { sendTelegramMessage };
export { deleteTelegramMessage, sendTelegramDocument, sendTelegramMessage };
64 changes: 60 additions & 4 deletions src/stateless.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
import axios from "axios";
import fs from "fs";
import path from "path";

/**
* Send a message to a Telegram recipient
* Send a message to a Telegram chat
* @param token
* @param recipientId
* @param chatId
* @param text
* @param mode
*/
export async function sendTelegramMessage(
token: string,
recipientId: number,
chatId: number,
text: string,
mode: "html" | "markdown",
): Promise<boolean> {
const telegramUrl = `https://api.telegram.org/bot${token}/sendMessage`;
try {
await axios.post(telegramUrl, {
chat_id: recipientId,
chat_id: chatId,
parse_mode: mode,
text,
});
Expand All @@ -26,3 +28,57 @@ export async function sendTelegramMessage(
}
return false;
}

/**
* Send a document to a Telegram chat
* @param token
* @param chatId
* @param filePath
* @param customFileName
*/
export async function sendTelegramDocument(
token: string,
chatId: number,
filePath: string,
customFileName?: string,
): Promise<boolean> {
const telegramUrl = `https://api.telegram.org/bot${token}/sendDocument`;
try {
const fileContent = await fs.promises.readFile(path.resolve(filePath));
const fileName = customFileName || path.basename(filePath);
// eslint-disable-next-line n/no-unsupported-features/node-builtins
const form = new FormData();
form.append("chat_id", chatId.toString());
form.append("document", new Blob([fileContent]), fileName);

await axios.post(telegramUrl, form);
return true;
} catch (error) {
console.error(`Failed to send document:`, error);
}
return false;
}

/**
* Delete a message from a Telegram chat
* @param token
* @param chatId
* @param messageId
*/
export async function deleteTelegramMessage(
token: string,
chatId: number,
messageId: number,
): Promise<boolean> {
const telegramUrl = `https://api.telegram.org/bot${token}/deleteMessage`;
try {
await axios.post(telegramUrl, {
chat_id: chatId,
message_id: messageId,
});
return true;
} catch (error) {
console.error(`Failed to delete message:`, error);
}
return false;
}
70 changes: 0 additions & 70 deletions test/index.test.ts

This file was deleted.

161 changes: 161 additions & 0 deletions test/stateless.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import { expect } from "chai";
import sinon from "sinon";
import axios from "axios";
import fs from "fs";

import {
deleteTelegramMessage,
sendTelegramDocument,
sendTelegramMessage,
} from "../src/stateless.js";

describe("sendTelegramMessage", () => {
let sandbox: sinon.SinonSandbox;

beforeEach(() => {
sandbox = sinon.createSandbox();
});

afterEach(() => {
sandbox.restore();
});

it("should return true on successful message send", async () => {
const axiosPostStub = sandbox.stub(axios, "post").resolves();
const result = await sendTelegramMessage(
"dummy_token",
12345,
"Hello, World!",
"markdown",
);
expect(result).to.be.true;
expect(axiosPostStub.calledOnce).to.be.true;
});

it("should return false on API failure", async () => {
sandbox.stub(axios, "post").rejects(new Error("Network error"));
const result = await sendTelegramMessage(
"dummy_token",
12345,
"Hello, World!",
"markdown",
);
expect(result).to.be.false;
});

it("should call axios.post with correct URL and payload", async () => {
const axiosPostStub = sandbox.stub(axios, "post").resolves();
await sendTelegramMessage("dummy_token", 12345, "Test Message", "html");
expect(
axiosPostStub.calledWith(
sinon.match.string,
sinon.match.has("chat_id", 12345) &&
sinon.match.has("text", "Test Message") &&
sinon.match.has("parse_mode", "html"),
),
).to.be.true;
});

it("should log error on failure", async () => {
const consoleErrorStub = sandbox.stub(console, "error");
sandbox.stub(axios, "post").rejects(new Error("Failed to send"));
await sendTelegramMessage(
"dummy_token",
12345,
"Hello, World!",
"markdown",
);
expect(
consoleErrorStub.calledWith(
sinon.match.string,
sinon.match.instanceOf(Error),
),
).to.be.true;
});
});

describe("sendTelegramDocument", () => {
let sandbox: sinon.SinonSandbox;

beforeEach(() => {
sandbox = sinon.createSandbox();
});

afterEach(() => {
sandbox.restore();
});

it("should return true on successful document send", async () => {
const axiosPostStub = sandbox.stub(axios, "post").resolves();
const fsReadFileStub = sandbox
.stub(fs.promises, "readFile")
.resolves(Buffer.from("dummy content"));
const result = await sendTelegramDocument(
"dummy_token",
12345,
"path/to/document",
);
expect(result).to.be.true;
expect(axiosPostStub.calledOnce).to.be.true;
expect(fsReadFileStub.calledOnceWith(sinon.match.string)).to.be.true;
});

it("should return false on API failure", async () => {
sandbox.stub(axios, "post").rejects(new Error("Network error"));
const result = await sendTelegramDocument(
"dummy_token",
12345,
"path/to/document",
);
expect(result).to.be.false;
});

it("should log error on failure", async () => {
const consoleErrorStub = sandbox.stub(console, "error");
sandbox.stub(axios, "post").rejects(new Error("Failed to send document"));
await sendTelegramDocument("dummy_token", 12345, "path/to/document");
expect(
consoleErrorStub.calledWith(
sinon.match.string,
sinon.match.instanceOf(Error),
),
).to.be.true;
});
});

describe("deleteTelegramMessage", () => {
let sandbox: sinon.SinonSandbox;

beforeEach(() => {
sandbox = sinon.createSandbox();
});

afterEach(() => {
sandbox.restore();
});

it("should return true on successful message deletion", async () => {
const axiosPostStub = sandbox.stub(axios, "post").resolves();
const result = await deleteTelegramMessage("dummy_token", 12345, 67890);
expect(result).to.be.true;
expect(axiosPostStub.calledOnce).to.be.true;
});

it("should return false on API failure", async () => {
sandbox.stub(axios, "post").rejects(new Error("Network error"));
const result = await deleteTelegramMessage("dummy_token", 12345, 67890);
expect(result).to.be.false;
});

it("should log error on failure", async () => {
const consoleErrorStub = sandbox.stub(console, "error");
sandbox.stub(axios, "post").rejects(new Error("Failed to delete message"));
await deleteTelegramMessage("dummy_token", 12345, 67890);
expect(
consoleErrorStub.calledWith(
sinon.match.string,
sinon.match.instanceOf(Error),
),
).to.be.true;
});
});

0 comments on commit 0cf2253

Please sign in to comment.