fasting-tracker
Version:
Türkiye'deki şehirler için iftar ve sahur saatlerini getiren, geri sayım, canlı timer, çoklu şehir desteği ve Discord Webhook entegrasyonu sunan Node.js paketi.
213 lines (180 loc) • 7.45 kB
JavaScript
const fetch = require("node-fetch");
const API_URL = "https://utku.berkaykoc.net/api/entertainment/fast-track";
/**
* Fetches iftar and sahur times for a given city.
* @param {string} city - The city name.
* @returns {Promise<Object>} - Returns an object with imsak (sahur) and iftar times.
*/
async function getFastTrack(city) {
try {
if (!city || typeof city !== "string") {
throw new Error("City name is required.");
}
const response = await fetch(`${API_URL}?city=${encodeURIComponent(city)}`);
if (!response.ok) {
throw new Error(`HTTP Error: ${response.status}`);
}
const data = await response.json();
return data;
} catch (error) {
throw new Error(`FastTrack API error: ${error.message}`);
}
}
/**
* Gets remaining time until iftar or sahur.
* @param {string} city - The city name.
* @param {string} [type="iftar"] - "imsak" or "iftar".
* @returns {Promise<Object>} - Remaining time info.
*/
async function getCountdown(city, type = "iftar") {
const times = await getFastTrack(city);
if (!times[type]) {
throw new Error(`Invalid time type: ${type}. Use "imsak" or "iftar".`);
}
const now = new Date();
const [hour, minute] = times[type].split(":").map(Number);
const targetTime = new Date(now.getFullYear(), now.getMonth(), now.getDate(), hour, minute, 0);
const diff = targetTime - now;
if (diff <= 0) {
return {
city: times.city || city,
type,
time: times[type],
passed: true,
message: `${type === "iftar" ? "🌅 İftar" : "🕓 Sahur"} vakti geçti.`,
remaining: null,
};
}
const hours = Math.floor(diff / 3600000);
const minutes = Math.floor((diff % 3600000) / 60000);
const seconds = Math.floor((diff % 60000) / 1000);
return {
city: times.city || city,
type,
time: times[type],
passed: false,
remaining: { hours, minutes, seconds },
remainingText: `${hours} saat ${minutes} dakika ${seconds} saniye`,
message: `${type === "iftar" ? "🌅 İftar" : "🕓 Sahur"} vaktine ${hours} saat ${minutes} dakika kaldı.`,
};
}
/**
* Gets iftar and sahur times for multiple cities at once.
* @param {string[]} cities - Array of city names.
* @returns {Promise<Object[]>} - Array of time data for each city.
*/
async function getMultipleCities(cities) {
if (!Array.isArray(cities) || cities.length === 0) {
throw new Error("Please provide an array of city names.");
}
const results = await Promise.allSettled(
cities.map(async (city) => {
const data = await getFastTrack(city);
return data;
})
);
return results.map((result, index) => {
if (result.status === "fulfilled") {
return result.value;
}
return { city: cities[index], error: result.reason.message };
});
}
/**
* Gets a formatted display string for a city's fasting times.
* @param {string} city - The city name.
* @returns {Promise<string>} - Formatted display string.
*/
async function getFormattedTimes(city) {
const times = await getFastTrack(city);
const countdown = await getCountdown(city, "iftar");
let output = `\n🌙 ═══════════════════════════════\n`;
output += ` ${(times.city || city).toUpperCase()} - Ramazan Vakitleri\n`;
output += `═══════════════════════════════\n`;
output += ` 🕓 Sahur (İmsak): ${times.imsak}\n`;
output += ` 🌅 İftar: ${times.iftar}\n`;
output += `───────────────────────────────\n`;
if (!countdown.passed) {
output += ` ⏳ İftara Kalan: ${countdown.remainingText}\n`;
} else {
output += ` ✅ İftar vakti geçti.\n`;
}
output += `═══════════════════════════════\n`;
return output;
}
/**
* Starts a live countdown timer in the console.
* @param {string} city - The city name.
* @param {string} [type="iftar"] - "imsak" or "iftar".
* @param {Function} [onTick] - Optional callback for each tick.
* @returns {Promise<Object>} - Returns interval ID and stop function.
*/
async function startLiveCountdown(city, type = "iftar", onTick = null) {
const times = await getFastTrack(city);
if (!times[type]) {
throw new Error(`Invalid time type: ${type}`);
}
const [hour, minute] = times[type].split(":").map(Number);
const intervalId = setInterval(() => {
const now = new Date();
const targetTime = new Date(now.getFullYear(), now.getMonth(), now.getDate(), hour, minute, 0);
const diff = targetTime - now;
if (diff <= 0) {
console.log(`\n🎉 ${type === "iftar" ? "İFTAR" : "SAHUR"} VAKTİ GELDİ! - ${times.city || city}`);
clearInterval(intervalId);
return;
}
const h = Math.floor(diff / 3600000);
const m = Math.floor((diff % 3600000) / 60000);
const s = Math.floor((diff % 60000) / 1000);
const display = `⏳ ${times.city || city} | ${type === "iftar" ? "İftar" : "Sahur"}: ${times[type]} | Kalan: ${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;
if (onTick) {
onTick({ hours: h, minutes: m, seconds: s, display });
} else {
process.stdout.write(`\r${display}`);
}
}, 1000);
return {
intervalId,
stop: () => clearInterval(intervalId),
};
}
/**
* Sets a reminder for iftar or sahur, with optional Discord webhook notifications.
* @param {string} city - The city name.
* @param {string} type - "imsak" or "iftar".
* @param {number} minutesBefore - Minutes before the time to send a reminder.
* @param {string} [webhookUrl] - Optional Discord webhook URL.
*/
async function setReminder(city, type = "iftar", minutesBefore = 10, webhookUrl = "") {
const times = await getFastTrack(city);
if (!times[type]) {
throw new Error(`Invalid time type: ${type}`);
}
const now = new Date();
const [hour, minute] = times[type].split(":").map(Number);
const targetTime = new Date(now.getFullYear(), now.getMonth(), now.getDate(), hour, minute, 0);
const reminderTime = new Date(targetTime - minutesBefore * 60 * 1000);
const delay = reminderTime - now;
if (delay <= 0) {
throw new Error(`The specified time has already passed.`);
}
console.log(`✅ Reminder set for ${city} - ${type} in ${minutesBefore} minutes before (at ${reminderTime.toLocaleTimeString()}).`);
setTimeout(async () => {
const message = `🔔 **Hatırlatma:** ${city} için **${type.toUpperCase()}** vaktine ${minutesBefore} dakika kaldı! (${times[type]})`;
console.log(message);
if (webhookUrl) {
try {
await fetch(webhookUrl, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ content: message })
});
console.log("✅ Notification sent to Discord webhook.");
} catch (error) {
console.error("❌ Failed to send Discord webhook:", error.message);
}
}
}, delay);
}
module.exports = { getFastTrack, setReminder, getCountdown, getMultipleCities, getFormattedTimes, startLiveCountdown };