goat
command
autotimer
Auto Islamic Timer
0
views
0
likes
0
installs
raw source
const moment = require("moment-timezone");
const axios = require("axios");
const fs = require("fs-extra");
const path = require("path");
const cacheFullPath = path.resolve(__dirname, "cache", "autotimer");
function ensureCacheDir() {
try {
if (typeof cacheFullPath === "string") {
fs.ensureDirSync(cacheFullPath);
}
} catch (e) {
console.log("[AutoTimer] Failed to create cache dir:", e.message);
}
}
const timerData = {
"12:00 AM": {
text: `╭━━━〔 🌙 গভীর রাত 〕━━━╮
🌌 রাতের এই নীরবতা আল্লাহর এক অপূর্ব নিয়ামত।
🤲 একটু জিকির করুন, দোয়া করুন এবং শান্তিতে বিশ্রাম নিন।
﴾ سُبْحَانَ اللّٰهِ وَبِحَمْدِهِ ﴿
╰━━━━━━━━━━━━━━━━━━━╯`,
video: "https://files.catbox.moe/7ch5ym.mp4"
},
"01:00 AM": {
text: `╭━━━〔 🌌 রাত ১টা 〕━━━╮
✨ তারাভরা আকাশ সাক্ষী—আল্লাহর সৃষ্টি কত নিখুঁত!
😴 সুস্থ থাকার জন্য এখন বিশ্রাম নিন।
﴾ الْحَمْدُ لِلّٰهِ ﴿
╰━━━━━━━━━━━━━━━━━━━╯`,
video: "https://files.catbox.moe/rqnlpt.mp4"
},
"02:00 AM": {
text: `╭━━━〔 🌠 রাত ২টা 〕━━━╮
🍃 প্রকৃতির নীরবতা আমাদের শেখায়,
সব নিয়ামতই মহান আল্লাহর পক্ষ থেকে।
🤲 আলহামদুলিল্লাহ
╰━━━━━━━━━━━━━━━━━━━╯`,
video: "https://files.catbox.moe/ev7guv.mp4"
},
"03:00 AM": {
text: `╭━━━〔 🌃 রাত ৩টা 〕━━━╮
🌙 রাতের শেষ প্রহর—
আল্লাহকে স্মরণ করার এক সুন্দর সময়।
﴾ أَسْتَغْفِرُ اللّٰهَ ﴿
╰━━━━━━━━━━━━━━━━━━━╯`,
video: "https://files.catbox.moe/rijx8m.mp4"
},
"04:30 AM": {
text: `╭━━━〔 🌅 𝐅𝐀𝐉𝐑 • ফজরের সময় 〕━━━╮
﴾ ﷽ ﴿
اَلصَّلَاةُ خَيْرٌ مِّنَ النَّوْمِ
🤲 আর কিছুক্ষণ পর ফজরের নামাজের সময় হবে।
🕌 সবাই অজু করে নামাজের জন্য প্রস্তুতি নিন।
اللَّهُمَّ اجْعَلْنَا مِنَ الْمُقِيمِينَ لِلصَّلَاةِ
╰━━━━━━━━━━━━━━━━━━━╯`,
video: "https://files.catbox.moe/ee9khu.mp4"
},
"06:00 AM": {
text: `╭━━━〔 ☀️ শুভ সকাল 〕━━━╮
🌿 নতুন সূর্যের আলো আল্লাহর অশেষ রহমতের নিদর্শন।
✨ আলহামদুলিল্লাহ বলে দিনটি শুরু হোক।
🤍 আল্লাহ সবাইকে হেফাজত করুন।
╰━━━━━━━━━━━━━━━━━━━╯`,
video: "https://files.catbox.moe/otdztt.mp4"
},
"07:00 AM": {
text: `╭━━━〔 🌸 সকাল ৭টা 〕━━━╮
🍀 সকালের নির্মল বাতাস,
সবুজ প্রকৃতি আর আল্লাহর অশেষ নিয়ামত।
💚 হাসিমুখে দিন শুরু করুন।
╰━━━━━━━━━━━━━━━━━━━╯`,
video: "https://files.catbox.moe/q6b7fo.mp4"
},
"08:00 AM": {
text: `╭━━━〔 🌤️ সকাল ৮টা 〕━━━╮
🌱 প্রতিটি নতুন সকাল
আল্লাহর দেওয়া একটি নতুন সুযোগ।
✨ নেক আমলে কাটুক আজকের দিন।
╰━━━━━━━━━━━━━━━━━━━╯`,
video: "https://files.catbox.moe/jxa3ka.mp4"
},
"09:00 AM": {
text: `╭━━━〔 🌞 সকাল ৯টা 〕━━━╮
🌳 প্রকৃতির সৌন্দর্য দেখুন,
আল্লাহর সৃষ্টি নিয়ে চিন্তা করুন।
🤲 আলহামদুলিল্লাহ
╰━━━━━━━━━━━━━━━━━━━╯`,
video: "https://files.catbox.moe/wtu9vw.mp4"
},
"10:00 AM": {
text: `╭━━━〔 🌼 সকাল ১০টা 〕━━━╮
🌺 ফুল, আকাশ আর সবুজ পৃথিবী—
সবই মহান আল্লাহর সৃষ্টি।
🤍 শুকরিয়া আল্লাহ।
╰━━━━━━━━━━━━━━━━━━━╯`,
video: "https://files.catbox.moe/guv0tc.mp4"
},
"11:00 AM": {
text: `╭━━━〔 🌿 সকাল ১১টা 〕━━━╮
🍃 ব্যস্ততার মাঝেও
আল্লাহর অগণিত নিয়ামতের জন্য
শুকরিয়া আদায় করুন।
╰━━━━━━━━━━━━━━━━━━━╯`,
video: "https://files.catbox.moe/aecxiz.mp4"
},
"12:00 PM": {
text: `╭━━━〔 ☀️ দুপুর ১২টা 〕━━━╮
🌏 সুন্দর এই পৃথিবী
মহান আল্লাহর এক অসীম নিয়ামত।
💚 সবার জন্য দোয়া রইল।
╰━━━━━━━━━━━━━━━━━━━╯`,
video: "https://files.catbox.moe/wrc15v.mp4"
},
"01:00 PM": {
text: `╭━━━〔 🕌 𝐙𝐔𝐇𝐑 • যোহরের সময় 〕━━━╮
﴾ ﷽ ﴿
حَيَّ عَلَى الصَّلَاةِ
🤲 আর কিছুক্ষণ পর যোহরের নামাজের সময় হবে।
🕌 সবাই নামাজের জন্য প্রস্তুতি নিন।
رَبِّ اجْعَلْنِي مُقِيمَ الصَّلَاةِ
╰━━━━━━━━━━━━━━━━━━━╯`,
video: "https://files.catbox.moe/c5qbek.mp4"
},
"02:00 PM": {
text: `╭━━━〔 🌳 দুপুর ২টা 〕━━━╮
🍃 প্রকৃতির মাঝে কিছুটা সময় কাটান।
🤲 সর্বদা আল্লাহর ওপর ভরসা রাখুন।
﴾ حَسْبُنَا اللَّهُ ﴿
╰━━━━━━━━━━━━━━━━━━━╯`,
video: "https://files.catbox.moe/vgecfk.mp4"
},
"03:00 PM": {
text: `╭━━━〔 🌅 বিকেল ৩টা 〕━━━╮
🍂 বিকেলের মৃদু হাওয়া
মনে করিয়ে দেয়—
আল্লাহর প্রতিটি সৃষ্টি সৌন্দর্যময়।
🤍 আলহামদুলিল্লাহ
╰━━━━━━━━━━━━━━━━━━━╯`,
video: "https://files.catbox.moe/iddna6.mp4"
},
"04:30 PM": {
text: `╭━━━〔 🕌 𝐀𝐒𝐑 • আসরের সময় 〕━━━╮
﴾ ﷽ ﴿
إِنَّ الصَّلَاةَ كَانَتْ عَلَى الْمُؤْمِنِينَ كِتَابًا مَوْقُوتًا
🤲 আর কিছুক্ষণ পর আসরের নামাজের সময় হবে।
🕌 সবাই নামাজের জন্য প্রস্তুতি নিন।
اللَّهُمَّ تَقَبَّلْ مِنَّا
╰━━━━━━━━━━━━━━━━━━━╯`,
video: "https://files.catbox.moe/vcgbxq.mp4"
},
"06:30 PM": {
text: `╭━━━〔 🌇 𝐌𝐀𝐆𝐇𝐑𝐈𝐁 • মাগরিবের সময় 〕━━━╮
﴾ ﷽ ﴿
الله أكبر، الله أكبر
🤲 আর কিছুক্ষণ পর মাগরিবের নামাজের সময় হবে।
🕌 সবাই অজু করে নামাজের জন্য প্রস্তুতি নিন।
اللَّهُمَّ تَقَبَّلْ مِنَّا
╰━━━━━━━━━━━━━━━━━━━╯`,
video: "https://files.catbox.moe/y8pnz7.mp4"
},
"08:00 PM": {
text: `╭━━━〔 🌙 𝐈𝐒𝐇𝐀 • এশার সময় 〕━━━╮
﴾ ﷽ ﴿
بِسْمِ اللَّهِ الرَّحْمَٰنِ الرَّحِيمِ
🤲 আর কিছুক্ষণ পর এশার নামাজের সময় হবে।
🕌 সবাই নামাজের জন্য প্রস্তুতি নিন।
آمِين يَا رَبَّ الْعَالَمِينَ
╰━━━━━━━━━━━━━━━━━━━╯`,
video: "https://files.catbox.moe/rpnut9.mp4"
},
"09:00 PM": {
text: `╭━━━〔 🌙 রাত ৯টা 〕━━━╮
✨ রাতের শান্ত আকাশ
আল্লাহর অসীম মহিমার সাক্ষী।
🤲 আজকের সকল নিয়ামতের জন্য
শুকরিয়া আদায় করুন।
╰━━━━━━━━━━━━━━━━━━━╯`,
video: "https://files.catbox.moe/fpac7y.mp4"
},
"10:00 PM": {
text: `╭━━━〔 🌌 রাত ১০টা 〕━━━╮
🌠 আল্লাহর হেফাজতের দোয়া করে
শান্তিতে বিশ্রাম নিন।
🤍 শুভ রাত্রি।
╰━━━━━━━━━━━━━━━━━━━╯`,
video: "https://files.catbox.moe/e7v8en.mp4"
},
"11:00 PM": {
text: `╭━━━〔 🌃 রাত ১১টা 〕━━━╮
🌙 নীরব রাত, শীতল বাতাস
আর আল্লাহর রহমত।
🤲 আগামী দিনটি হোক
কল্যাণময় ও বরকতময়।
✨ آمين يا رب العالمين ✨
╰━━━━━━━━━━━━━━━━━━━╯`,
video: "https://files.catbox.moe/7bas7j.mp4"
}
};
let sentMap = new Map();
let interval = null;
module.exports = {
config: {
name: "autotimer",
version: "2.3",
author: "Riyad (Upgraded)",
countDown: 5,
role: 2,
shortDescription: {
en: "Auto Islamic Timer"
},
longDescription: {
en: "Sends automatic time-based Islamic messages with video"
},
category: "system",
guide: {
en: "{pn} on / off / status / next / reload / list"
}
},
onStart: async function ({ message, args, event, threadsData }) {
const threadID = event.threadID;
const sub = (args[0] || "").toLowerCase();
switch (sub) {
case "on": {
await threadsData.set(threadID, true, "data.autoTimer");
return message.reply("✅ এই গ্রুপে AutoTimer ON করা হয়েছে।");
}
case "off": {
await threadsData.set(threadID, false, "data.autoTimer");
return message.reply("❌ এই গ্রুপে AutoTimer OFF করা হয়েছে।");
}
case "status": {
// FIX: guard against threadsData.get() throwing or returning
// undefined for a thread with no stored data yet — default to ON.
let threadData;
try {
threadData = await threadsData.get(threadID);
} catch (e) {
threadData = null;
}
const isOn = threadData?.data?.autoTimer !== false;
return message.reply(`📊 AutoTimer Status: ${isOn ? "ON ✅" : "OFF ❌"}`);
}
case "next": {
// Shows the next upcoming timer slot and how long until it fires,
// so admins don't have to guess which slots exist or wait blindly.
const now = moment().tz("Asia/Dhaka");
const upcoming = Object.keys(timerData)
.map((label) => {
const slot = moment.tz(label, "hh:mm A", "Asia/Dhaka");
let target = now.clone().set({
hour: slot.hour(),
minute: slot.minute(),
second: 0,
millisecond: 0
});
if (target.isSameOrBefore(now)) target.add(1, "day");
return { label, target };
})
.sort((a, b) => a.target.valueOf() - b.target.valueOf())[0];
const diffMin = upcoming.target.diff(now, "minutes");
const hours = Math.floor(diffMin / 60);
const mins = diffMin % 60;
const remaining = hours > 0 ? `${hours} ঘণ্টা ${mins} মিনিট` : `${mins} মিনিট`;
return message.reply(
`⏳ পরবর্তী টাইমার ➜ ${upcoming.label}\n🕒 বাকি সময় ➜ প্রায় ${remaining}`
);
}
case "reload": {
// Deletes the cached video for the CURRENT slot only, forcing a
// fresh re-download on the next matching tick — useful if a
// download got corrupted or the source video changed.
const now = moment().tz("Asia/Dhaka").format("hh:mm A");
const videoFileName = now.replace(/[: ]/g, "_") + ".mp4";
const videoFullPath = path.resolve(cacheFullPath, videoFileName);
try {
if (fs.existsSync(videoFullPath)) {
fs.removeSync(videoFullPath);
return message.reply(`♻️ ক্যাশ রিলোড করা হয়েছে (${now})। পরের বার নতুন ভিডিও ডাউনলোড হবে।`);
}
return message.reply(`ℹ️ এই স্লটের (${now}) জন্য কোনো ক্যাশ করা ভিডিও পাওয়া যায়নি।`);
} catch (e) {
return message.reply("⚠️ রিলোড করতে সমস্যা হয়েছে: " + e.message);
}
}
case "list": {
const slots = Object.keys(timerData).join(", ");
return message.reply(`🗒️ সকল টাইমার স্লট:\n${slots}`);
}
default: {
return message.reply(
"📌 ব্যবহার করুন:\n" +
"• autotimer on — এই গ্রুপে চালু করুন\n" +
"• autotimer off — এই গ্রুপে বন্ধ করুন\n" +
"• autotimer status — বর্তমান অবস্থা দেখুন\n" +
"• autotimer next — পরবর্তী টাইমার কখন দেখুন\n" +
"• autotimer reload — বর্তমান স্লটের ক্যাশ রিসেট করুন\n" +
"• autotimer list — সব টাইমার স্লট দেখুন"
);
}
}
},
onLoad: function ({ api, threadsData }) {
if (interval) return;
// Directory creation happens here, on the first tick — never during
// require() — and is wrapped so a failure here only skips this cycle
// instead of preventing the whole command from loading.
ensureCacheDir();
console.log("[AutoTimer] Started successfully!");
interval = setInterval(async () => {
try {
ensureCacheDir(); // safe to call repeatedly; ensureDirSync is a no-op if it already exists
const now = moment().tz("Asia/Dhaka").format("hh:mm A");
const today = moment().tz("Asia/Dhaka").format("DD-MM-YYYY");
const data = timerData[now];
if (!data) return;
// FIX: the old key was a broken template literal
// (`\( {today}_ \){now}`) that never actually interpolated
// `today`/`now` — it produced the exact same literal string every
// time, so after the very first send, sentMap.has(key) was always
// true and no further times ever went out.
const key = `${today}_${now}`;
if (sentMap.has(key)) return;
sentMap.set(key, true);
if (sentMap.size > 40) sentMap.clear();
if (typeof now !== "string" || typeof cacheFullPath !== "string") {
console.log("[AutoTimer] now/cacheFullPath not a string, skipping this tick.");
return;
}
const videoFileName = now.replace(/[: ]/g, "_") + ".mp4";
const videoFullPath = path.resolve(cacheFullPath, videoFileName);
if (typeof videoFullPath !== "string") {
console.log("[AutoTimer] videoFullPath failed to resolve to a string, skipping.");
return;
}
// Download video
if (!fs.existsSync(videoFullPath)) {
try {
const res = await axios.get(data.video, {
responseType: "arraybuffer",
timeout: 60000
});
fs.writeFileSync(videoFullPath, Buffer.from(res.data));
} catch (e) {
console.log("[AutoTimer] Video download error:", e.message);
return;
}
}
// Guard: make sure the file actually exists and is a string path
// before we ever hand it to fs.createReadStream / api.sendMessage.
if (!fs.existsSync(videoFullPath)) {
console.log("[AutoTimer] videoFullPath missing after download attempt, skipping send.");
return;
}
const body =
`🕒 𝐓𝐈𝐌𝐄 ➜ ${now}
📅 𝐃𝐀𝐓𝐄 ➜ ${today}
${data.text}
👑 𝐌𝐚𝐑𝐮𝐅'𝐬 𝐁𝐨𝐓 💫🪽`;
// Get all groups
let threads = [];
try {
threads = await api.getThreadList(200, null, ["INBOX"]);
} catch (e) {
return;
}
const groups = threads.filter(t => t.isGroup);
for (const thread of groups) {
try {
// Respect per-thread on/off state (default = ON if never set)
let enabled = true;
try {
const td = await threadsData.get(thread.threadID);
enabled = td?.data?.autoTimer !== false;
} catch (e) {
// if thread data can't be read, default to sending
}
if (!enabled) continue;
await api.sendMessage({
body,
attachment: fs.createReadStream(videoFullPath)
}, thread.threadID);
await new Promise(r => setTimeout(r, 1000)); // anti spam
} catch (err) {
// ignore individual errors
}
}
console.log(`[AutoTimer] Sent → ${now}`);
} catch (err) {
console.log("[AutoTimer] Main error:", err.message);
}
}, 30000); // 30 seconds
}
};