Compare commits

...

10 commits

9 changed files with 149 additions and 3 deletions

View file

@ -1 +1,4 @@
PORT=3000
PORT=3000
TELEGRAM_API_TOKEN=
TELEGRAM_CHAT_ID=

View file

@ -1,6 +1,6 @@
FROM node:22-alpine
WORKDIR /usr/src/app
WORKDIR /app
COPY package*.json ./

View file

@ -4,5 +4,5 @@ services:
container_name: parchex-bot
restart: unless-stopped
volumes:
- .:/usr/src/app
- .:/app
network_mode: host

10
nodemon.json Normal file
View file

@ -0,0 +1,10 @@
{
"watch": [
"main.js"
],
"ext": "js,json",
"ignore": [
"node_modules"
],
"exec": "node src/main.js"
}

35
src/apis/main.js Normal file
View file

@ -0,0 +1,35 @@
import axios from "axios";
import { log } from "../utils/logger.js";
const getLatestPost = async () => {
try {
const latestpostUrl = "https://forum.parchlinux.com/latest.json";
const response = await axios.get(latestpostUrl);
const topics = response?.data?.topic_list?.topics;
if (!Array.isArray(topics) || topics.length === 0) {
log.warn("No topics found in latest post data");
return null;
}
const latestPost = topics.find(t => !t.pinned);
if (!latestPost) {
log.warn("No non-pinned topic found");
return null;
}
log.info("Fetched latest post successfully");
return {
title: latestPost.title,
excerpt: latestPost.excerpt,
url: `https://forum.parchlinux.com/t/${latestPost.slug}/${latestPost.id}`,
};
} catch (error) {
log.error("Error fetching latest post:", error?.message || error);
return null;
}
};
export { getLatestPost };

15
src/configs/main.js Normal file
View file

@ -0,0 +1,15 @@
import dotenv from "dotenv";
dotenv.config();
const Configs = {
app: {
port: process.env.PORT || 3000
},
bot: {
apiToken: process.env.TELEGRAM_API_TOKEN,
chatId: process.env.TELEGRAM_CHAT_ID
}
};
export default Configs;

35
src/main.js Normal file
View file

@ -0,0 +1,35 @@
import { getLatestPost } from "./apis/main.js";
import { sendMessage } from "./services/messageServices.js";
import { log } from "./utils/logger.js";
let lastSentPostId = null;
const sendLatestPost = async () => {
const post = await getLatestPost();
if (post) {
if (post.id !== lastSentPostId) {
const message = `- آخرین پست از انجمن #پارچ لینوکس\n` +
`عنوان موضوع: ${post.title}\n` +
`توضیحات: ${post.excerpt}\n` +
`پیوند: ${post.url}`;
try {
await sendMessage(message, { parse_mode: 'Markdown' });
lastSentPostId = post.id;
log.info("Latest post sent successfully");
} catch (error) {
log.error("Error sending message:", error);
}
} else {
log.info("No new post to send.");
}
} else {
log.warn("No post found to send");
}
};
setInterval(sendLatestPost, 60 * 60 * 1000);
sendLatestPost();

View file

@ -0,0 +1,16 @@
import { Telegraf } from "telegraf";
import configs from "../configs/main.js";
import { log } from "../utils/logger.js";
const bot = new Telegraf(configs.bot.apiToken);
const sendMessage = async (message) => {
try {
await bot.telegram.sendMessage(configs.bot.chatId, message);
log.info("Message sent successfully");
} catch (error) {
log.error("Error sending message:", error);
}
};
export { sendMessage };

32
src/utils/logger.js Normal file
View file

@ -0,0 +1,32 @@
import winston from "winston";
const logger = () => {
try {
return winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.colorize(),
winston.format.simple()
),
transports: [
new winston.transports.Console(),
new winston.transports.File({
filename: 'logs/bot.log',
options: { flags: 'a' },
level: 'info',
async: true
})
]
});
} catch (error) {
console.error('Logger creation failed:', error);
}
};
const log = logger();
if (log) {
log.info('Bot started');
}
export { log };