bid-tool/auto-bid-server/src/modules/bids/apis/bot-telegram.api.ts

150 lines
4.9 KiB
TypeScript

import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import axios from 'axios';
import * as dayjs from 'dayjs';
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
import { join } from 'path';
import { Bid } from '../entities/bid.entity';
import { Constant } from '../utils/constant';
@Injectable()
export class BotTelegramApi {
private readonly botToken: string;
private readonly apiUrl: string;
constructor(private readonly configService: ConfigService) {
this.botToken = this.configService.get<string>('TELEGRAM_BOT_TOKEN');
this.apiUrl = `https://api.telegram.org/bot${this.botToken}`;
}
formatBidMessage(bid: Bid) {
return `<b>📢 New Bid Alert!</b>\n
<b>📌 Product:</b> ${bid.name ? `<b>${bid.name}</b>` : '_No name_'}\n
<b>💰 Current Price:</b> <code>${bid.current_price.toLocaleString()}${bid.plus_price ? ` (+${bid.plus_price.toLocaleString()})` : ''}</code>\n
<b>🏆 Max Price:</b> <code>${bid.max_price.toLocaleString()}</code>\n
<b>🔖 Starting Price:</b> <code>${bid.reserve_price.toLocaleString()}</code>\n\n
<b>📦 Model:</b> <code>${bid.model || 'None'}</code>\n
<b>🔢 Quantity:</b> <code>${bid.quantity}</code>\n
<b>🆔 Lot ID:</b> <code>${bid.lot_id ? bid.lot_id.toString() : 'None'}</code>\n\n
<b>⏳ Closing Time:</b> ${bid.close_time ? `<code>${dayjs(bid.close_time).format('HH:mm:ss DD/MM/YYYY')}</code>` : '_Not available_'}\n
<b>🚀 Start Time:</b> ${bid.start_bid_time ? `<code>${dayjs(bid.start_bid_time).format('HH:mm:ss DD/MM/YYYY')}</code>` : '_Not available_'}\n\n
<b>📈 Bid History:</b>\n${
bid.histories.length > 0
? bid.histories
.map(
(h, index) =>
` ${index + 1}. 💵 <code>${index === 0 ? '🔴' : ''}${h.price.toLocaleString()}</code> 🕒 <code>${dayjs(h.updated_at).format('HH:mm:ss DD/MM/YYYY')}</code>`,
)
.join('\n')
: '_No bid history yet_'
}\n\n
<b>📝 Status:</b> <code>${bid.status.replace('-', ' ')}</code>\n\n
⬇️ <b>View Details:</b> <a href="${bid.url}">Click here</a>`;
}
async sendMessage(
text: string,
bonusBody: Record<string, any> = {},
chatId: string = this.configService.get<string>('CHAT_ID'),
): Promise<void> {
try {
const url = `${this.apiUrl}/sendMessage`;
const response = await axios.post(
url,
{
chat_id: chatId,
text: text,
...bonusBody,
},
{
family: 4,
},
);
} catch (error) {
console.error('Error sending message:', error || error.message);
}
}
async createFolderPath(): Promise<string> {
const rootDir = process.cwd();
const folderPath = join(rootDir, `${Constant.BOT_TELEGRAM_PATH}`);
if (!existsSync(folderPath)) {
mkdirSync(folderPath, { recursive: true, mode: 0o777 });
// ✅ Lưu metadata lần đầu
const metadataPath = join(folderPath, 'metadata.json');
writeFileSync(
metadataPath,
JSON.stringify({ createdAt: Date.now() }),
'utf-8',
);
}
return folderPath;
}
async getGroupInfo(
chatId: string = this.configService.get<string>('CHAT_ID'),
): Promise<any> {
try {
const folderPath = await this.createFolderPath();
const metadataPath = join(folderPath, 'metadata.json');
const dataFilePath = join(folderPath, `group_${chatId}.json`);
// 10 minute
const TIME_TO_REFRESH_DATA = 10;
if (existsSync(metadataPath)) {
const metadata = JSON.parse(readFileSync(metadataPath, 'utf-8'));
const createdAt = metadata?.createdAt || 0;
const now = Date.now();
const diffMinutes = (now - createdAt) / 60000;
if (diffMinutes < TIME_TO_REFRESH_DATA && existsSync(dataFilePath)) {
return JSON.parse(readFileSync(dataFilePath, 'utf-8'));
}
}
const url = `${this.apiUrl}/getChat`;
const { data } = await axios({
url,
params: { chat_id: chatId },
family: 4,
});
if (data?.ok) {
writeFileSync(
dataFilePath,
JSON.stringify(data.result, null, 2),
'utf-8',
);
writeFileSync(
metadataPath,
JSON.stringify({ createdAt: Date.now() }),
'utf-8',
);
return data.result;
}
} catch (error) {
console.error(error || error.message);
}
}
async sendBidInfo(bid: Bid): Promise<boolean> {
try {
const text = this.formatBidMessage(bid);
await this.sendMessage(text, {
parse_mode: 'HTML',
});
return true;
} catch (error) {
console.log('SEND MESSAGE FAILURE');
return false;
}
}
}