// code from goatstore // api: https://store.agi.bd module.exports.config = { name: "news", version: "13.0.0", author: "Zihad", countDown: 5, role: 0, shortDescription: "Newspaper Reader", longDescription: "বাংলাদেশের বিভিন্ন পত্রিকার সর্বশেষ খবর পড়ুন", category: "news", guide: { en: "{pn}" } }; const https = require("https"); const http = require("http"); const PAPERS = [ { name: "প্রথম আলো", host: "prothomalo.com", url: "https://www.prothomalo.com/" }, { name: "নয়া দিগন্ত", host: "dailynayadiganta.com", url: "https://www.dailynayadiganta.com/" }, { name: "যুগান্তর", host: "jugantor.com", url: "https://www.jugantor.com/" }, { name: "কালের কণ্ঠ", host: "kalerkantho.com", url: "https://www.kalerkantho.com/" }, { name: "ইত্তেফাক", host: "ittefaq.com.bd", url: "https://www.ittefaq.com.bd/" }, { name: "সমকাল", host: "samakal.com", url: "https://samakal.com/" }, { name: "জাগো নিউজ", host: "jagonews24.com", url: "https://www.jagonews24.com/" }, { name: "বিডিনিউজ২৪", host: "bdnews24.com", url: "https://bdnews24.com/" } ]; /* ========================= HTTP REQUEST ========================= */ function request(url, redirects = 0) { return new Promise((resolve, reject) => { if (!url || redirects > 8) { return reject(new Error("Invalid URL")); } let client = https; try { if (new URL(url).protocol === "http:") { client = http; } } catch (e) { return reject(e); } const req = client.get( url, { headers: { "User-Agent": "Mozilla/5.0 (Linux; Android 12) AppleWebKit/537.36 Chrome/120.0 Mobile Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "bn-BD,bn;q=0.9,en-US;q=0.8,en;q=0.7", "Accept-Encoding": "identity", "Connection": "close" } }, res => { let data = ""; res.setEncoding("utf8"); res.on("data", chunk => { data += chunk; }); res.on("end", () => { const status = res.statusCode || 0; /* Redirect */ if ( status >= 300 && status < 400 && res.headers.location ) { let next = res.headers.location; try { next = new URL(next, url).href; } catch (e) {} return request(next, redirects + 1) .then(resolve) .catch(reject); } resolve({ status, body: data, finalUrl: url }); }); } ); req.setTimeout(20000, () => { req.destroy(new Error("Request timeout")); }); req.on("error", reject); }); } /* ========================= TEXT CLEANER ========================= */ function decode(text) { if (!text) return ""; return String(text) .replace(//gi, "") .replace(/ /gi, " ") .replace(/&/gi, "&") .replace(/"/gi, '"') .replace(/'/gi, "'") .replace(/'/gi, "'") .replace(/</gi, "<") .replace(/>/gi, ">") .replace(/&#(\d+);/g, (_, n) => String.fromCharCode(Number(n)) ) .replace(/&#x([0-9a-f]+);/gi, (_, n) => String.fromCharCode(parseInt(n, 16)) ); } function clean(text) { if (!text) return ""; let value = decode(text); value = value .replace(//gi, "") .replace(//gi, "") .replace(//gi, "") .replace(//gi, "") .replace(//gi, ""); value = value.replace(/<\/p\s*>/gi, "\n"); value = value.replace(//gi, "\n"); value = value.replace(/<\/div\s*>/gi, "\n"); value = value.replace(/<[^>]+>/g, " "); value = decode(value); /* Remove URLs from bot output */ value = value.replace( /https?:\/\/[^\s"'<>]+/gi, "" ); value = value.replace(/[ \t]+/g, " "); value = value.replace(/\n[ \t]+/g, "\n"); value = value.replace(/\n{3,}/g, "\n\n"); return value.trim(); } /* ========================= RSS PARSER ========================= */ function getTag(text, tag) { const regex = new RegExp( "<" + tag + "(?:\\s[^>]*)?>([\\s\\S]*?)<\\/" + tag + ">", "i" ); const match = text.match(regex); return match ? clean(match[1]) : ""; } function parseRSS(xml) { const items = xml.match(//gi) || []; const result = []; for (const item of items) { const title = getTag(item, "title"); const link = getTag(item, "link"); const description = getTag(item, "description"); const pubDate = getTag(item, "pubDate"); if (!title || !link) continue; result.push({ title, link, description, date: pubDate }); } return result; } /* ========================= GOOGLE NEWS RSS ========================= */ async function googleNews(paper) { const query = "site:" + paper.host + " when:2d"; const url = "https://news.google.com/rss/search?q=" + encodeURIComponent(query) + "&hl=bn&gl=BD&ceid=BD:bn"; const response = await request(url); if ( response.status < 200 || response.status >= 400 ) { throw new Error("Google RSS HTTP " + response.status); } const list = parseRSS(response.body); return list .filter(item => { return ( item.title && !item.title.toLowerCase().includes("terms") ); }) .slice(0, 8); } /* ========================= DIRECT WEBSITE FALLBACK ========================= */ function extractLinks(html, paper) { const results = []; if (!html) return results; const regex = /]*href=["']([^"']+)["'][^>]*>([\s\S]*?)<\/a>/gi; let match; while ((match = regex.exec(html)) !== null) { let link = match[1]; let title = clean(match[2]); if (!title) continue; if ( title.length < 15 || title.length > 250 ) { continue; } try { link = new URL(link, paper.url).href; } catch (e) { continue; } if (!link.includes(paper.host)) { continue; } /* Ignore unnecessary pages */ if ( /javascript:|mailto:|facebook|twitter|instagram|youtube/i.test( link ) ) { continue; } if ( /login|register|privacy|terms|contact|about/i.test( link ) ) { continue; } results.push({ title, link, description: "", date: "" }); } /* Remove duplicate links */ const seen = new Set(); return results.filter(item => { if (seen.has(item.link)) return false; seen.add(item.link); return true; }).slice(0, 8); } async function directNews(paper) { const response = await request(paper.url); if ( response.status < 200 || response.status >= 400 ) { throw new Error( "Website HTTP " + response.status ); } return extractLinks( response.body, paper ); } /* ========================= GET NEWS ========================= */ async function getNews(paper) { /* First try Google RSS */ try { const rss = await googleNews(paper); if (rss.length > 0) { return rss; } } catch (error) { console.log( "[NEWS RSS ERROR]", paper.name, error.message ); } /* If RSS fails, use newspaper website */ try { const direct = await directNews(paper); if (direct.length > 0) { return direct; } } catch (error) { console.log( "[DIRECT NEWS ERROR]", paper.name, error.message ); } return []; } /* ========================= ARTICLE EXTRACTOR ========================= */ function extractArticle(html) { if (!html) return ""; let best = ""; /* JSON-LD articleBody */ const scripts = html.match( /]+type=["']application\/ld\+json["'][^>]*>[\s\S]*?<\/script>/gi ) || []; for (const script of scripts) { try { const raw = script .replace(/]*>/i, "") .replace(/<\/script>/i, "") .trim(); const data = JSON.parse(raw); const objects = Array.isArray(data) ? data : [data]; for (const obj of objects) { if ( obj && typeof obj.articleBody === "string" ) { const body = clean( obj.articleBody ); if (body.length > best.length) { best = body; } } } } catch (e) {} } /* Article tag */ const articleMatch = html.match( /]*>([\s\S]*?)<\/article>/i ); if (articleMatch) { const body = clean( articleMatch[1] ); if (body.length > best.length) { best = body; } } /* Main tag */ const mainMatch = html.match( /]*>([\s\S]*?)<\/main>/i ); if (mainMatch) { const body = clean( mainMatch[1] ); if (body.length > best.length) { best = body; } } /* Common article classes */ const patterns = [ /]+class=["'][^"']*(article-body|article_content|article-content|story-content|news-content|news-body|content-body)[^"']*["'][^>]*>([\s\S]*?)<\/div>/gi, /]+class=["'][^"']*(article-body|article-content|story-content|news-content|news-body)[^"']*["'][^>]*>([\s\S]*?)<\/section>/gi ]; for (const pattern of patterns) { const matches = [ ...html.matchAll(pattern) ]; for (const m of matches) { const body = clean( m[m.length - 1] ); if (body.length > best.length) { best = body; } } } return best; } /* ========================= READ ARTICLE ========================= */ async function readArticle(item) { if (!item.link) { return ""; } try { const response = await request(item.link); if ( response.status >= 200 && response.status < 400 ) { const article = extractArticle(response.body); if (article.length >= 300) { return article; } } } catch (error) { console.log( "[ARTICLE REQUEST ERROR]", error.message ); } /* Jina fallback */ try { const jinaURL = "https://r.jina.ai/http://" + item.link.replace(/^https?:\/\//i, ""); const jina = await request(jinaURL); if ( jina.status >= 200 && jina.status < 400 ) { let text = clean(jina.body); text = text .replace(/^Title\s*:.*$/gim, "") .replace(/^URL\s*:.*$/gim, "") .replace(/^Published Time\s*:.*$/gim, "") .trim(); if (text.length >= 300) { return text; } } } catch (error) { console.log( "[JINA ERROR]", error.message ); } /* RSS description fallback */ if ( item.description && item.description.length > 80 ) { return clean(item.description); } return ""; } /* ========================= SPLIT LONG TEXT ========================= */ function splitText(text, max = 1800) { const parts = []; text = String(text || "").trim(); while (text.length > max) { let cut = text.lastIndexOf("\n", max); if (cut < 700) { cut = text.lastIndexOf("।", max); if (cut < 700) { cut = max; } else { cut++; } } parts.push( text.substring(0, cut).trim() ); text = text.substring(cut).trim(); } if (text) { parts.push(text); } return parts; } /* ========================= PAPER MENU ========================= */ function paperMenu() { let text = `╭━━〔 📰 NEWS PAPER 〕━━╮ ┃ 🇧🇩 বাংলাদেশের সংবাদপত্র ┃ `; PAPERS.forEach((paper, index) => { text += `┃ ${index + 1}. ${paper.name}\n`; }); text += `┃ ┃ 🔢 পত্রিকা বাছাই করতে নম্বর দিন ╰━━━━━━━━━━━━━━━━━━━━╯`; return text; } /* ========================= NEWS MENU ========================= */ function newsMenu(paper, news) { let text = `╭━━〔 📰 ${paper.name} 〕━━╮ ┃ 🕐 সর্বশেষ সংবাদ ┃ `; news.forEach((item, index) => { text += `┃ ${index + 1}. ${item.title}\n`; }); text += `┃ ┃ 📖 খবর পড়তে নম্বর রিপ্লাই করুন ╰━━━━━━━━━━━━━━━━━━━━╯`; return text; } /* ========================= START ========================= */ module.exports.onStart = async function ({ message }) { return message.reply( paperMenu(), (err, info) => { if ( err || !info || !info.messageID ) { return; } global.GoatBot.onReply.set( info.messageID, { commandName: "news", type: "papers" } ); } ); }; /* ========================= REPLY ========================= */ module.exports.onReply = async function ({ message, Reply, event }) { const input = String(event.body || "").trim(); if (!/^\d+$/.test(input)) { return message.reply( "⚠️ শুধু নম্বর রিপ্লাই করুন।" ); } const number = Number(input); /* ========================= PAPER SELECT ========================= */ if (Reply.type === "papers") { if ( number < 1 || number > PAPERS.length ) { return message.reply( "❌ ভুল পত্রিকার নম্বর।" ); } const paper = PAPERS[number - 1]; await message.reply( `╭━━〔 ⏳ NEWS LOADING 〕━━╮ ┃ 📰 ${paper.name} ┃ ┃ সর্বশেষ খবর খোঁজা হচ্ছে... ╰━━━━━━━━━━━━━━━━━━━━╯` ); try { const news = await getNews(paper); if (!news.length) { return message.reply( `╭━━〔 ❌ NEWS ERROR 〕━━╮ ┃ ┃ 📰 ${paper.name} ┃ ┃ এই মুহূর্তে খবরের তালিকা ┃ পাওয়া যাচ্ছে না। ┃ ┃ 🔄 কিছুক্ষণ পরে আবার চেষ্টা করুন। ╰━━━━━━━━━━━━━━━━━━━━╯` ); } return message.reply( newsMenu(paper, news), (err, info) => { if ( err || !info || !info.messageID ) { return; } global.GoatBot.onReply.set( info.messageID, { commandName: "news", type: "articles", paper, news } ); } ); } catch (error) { console.log( "[NEWS ERROR]", error ); return message.reply( `╭━━〔 ❌ NEWS ERROR 〕━━╮ ┃ ┃ 📰 ${paper.name} ┃ ┃ খবর সার্ভার থেকে response ┃ পাওয়া যাচ্ছে না। ┃ ┃ 🔄 কিছুক্ষণ পরে আবার চেষ্টা করুন। ╰━━━━━━━━━━━━━━━━━━━━╯` ); } } /* ========================= ARTICLE SELECT ========================= */ if (Reply.type === "articles") { const news = Reply.news || []; if ( number < 1 || number > news.length ) { return message.reply( "❌ ভুল খবরের নম্বর।" ); } const item = news[number - 1]; await message.reply( `╭━━〔 📖 NEWS READER 〕━━╮ ┃ ┃ 🏷️ ${Reply.paper.name} ┃ ┃ 📰 ${item.title} ┃ ┃ ⏳ সংবাদটি পড়া হচ্ছে... ╰━━━━━━━━━━━━━━━━━━━━╯` ); try { let body = await readArticle(item); body = clean(body); /* Remove URLs */ body = body.replace( /https?:\/\/[^\s)]+/gi, "" ); if (body.length < 100) { return message.reply( `╭━━〔 ⚠️ NEWS READER 〕━━╮ ┃ ┃ 📰 ${item.title} ┃ ┃ এই খবরের বিস্তারিত লেখা ┃ এখন পাওয়া যাচ্ছে না। ┃ ┃ 📝 পাওয়া তথ্য: ┃ ${item.description || "তথ্য পাওয়া যায়নি।"} ╰━━━━━━━━━━━━━━━━━━━━╯` ); } /* * Full article copy না করে * প্রথম অংশ/সংক্ষিপ্ত readable content * Messenger-এ দেখানো হবে। */ const parts = splitText(body, 1800); await message.reply( `╭━━〔 📰 ${Reply.paper.name} 〕━━╮ ┃ ┃ 📰 ${item.title} ┃ ╰━━━━━━━━━━━━━━━━━━━━╯ 📖 সংবাদ: ${parts[0]}` ); /* * Additional extracted sections */ for ( let i = 1; i < parts.length && i < 3; i++ ) { await new Promise( resolve => setTimeout(resolve, 300) ); await message.reply( parts[i] ); } return message.reply( `╭━━〔 🤖 NEWS BOT 〕━━╮ ┃ 👤 Author: Zihad ┃ 📰 Newspaper Reader ┃ ┃ ✅ সংবাদ পড়া শেষ ╰━━━━━━━━━━━━━━━━━━━━╯` ); } catch (error) { console.log( "[ARTICLE ERROR]", error ); return message.reply( `╭━━〔 ⚠️ NEWS READER 〕━━╮ ┃ ┃ 📰 ${item.title} ┃ ┃ সংবাদটির লেখা এখন ┃ সংগ্রহ করা যাচ্ছে না। ┃ ┃ 🔄 পরে আবার চেষ্টা করুন। ╰━━━━━━━━━━━━━━━━━━━━╯` ); } } };