Back

Jadwal Sholat

55 views
rapp Code by: @rapp

Description

Mengambil jadwal sholat dari suatu daerah di Indonesia maupun di luar negara.

Features

Code (javascript)

jadwalsholat.js
const axios = require('axios');

class GlobalPrayerTime {
    constructor() {
        this.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
            'Accept': 'application/json'
        };
        this.axiosInstance = axios.create({
            timeout: 30000,
            headers: this.headers
        });
        
        // Cache untuk koordinat kota
        this.cityCache = new Map();
    }

    formatDate() {
        const now = new Date();
        const options = { 
            weekday: 'long', 
            year: 'numeric', 
            month: 'long', 
            day: 'numeric' 
        };
        return now.toLocaleDateString('id-ID', options);
    }

    getCurrentTime() {
        const now = new Date();
        return now.toLocaleTimeString('id-ID', { 
            hour: '2-digit', 
            minute: '2-digit', 
            second: '2-digit',
            hour12: false 
        });
    }

    async getCityCoordinates(city, country = '') {
        try {
            const cacheKey = `${city.toLowerCase()}_${country.toLowerCase()}`;
            if (this.cityCache.has(cacheKey)) {
                return this.cityCache.get(cacheKey);
            }

            // Gunakan Nominatim OpenStreetMap untuk geocoding
            const response = await this.axiosInstance.get(
                `https://nominatim.openstreetmap.org/search`,
                {
                    params: {
                        q: `${city} ${country}`,
                        format: 'json',
                        limit: 1
                    }
                }
            );

            if (response.data && response.data.length > 0) {
                const result = {
                    lat: parseFloat(response.data[0].lat),
                    lon: parseFloat(response.data[0].lon),
                    display_name: response.data[0].display_name
                };
                this.cityCache.set(cacheKey, result);
                return result;
            }

            throw new Error('Kota tidak ditemukan');

        } catch (error) {
            throw new Error(`Gagal mendapatkan koordinat kota: ${error.message}`);
        }
    }

    async getPrayerTimesByCoordinates(lat, lon, method = 1) {
        try {
            const today = new Date();
            const year = today.getFullYear();
            const month = today.getMonth() + 1;
            const day = today.getDate();

            // API 1: Aladhan API (Gratis, global)
            const api1 = await this.tryAladhanAPI(lat, lon, year, month, day, method);
            if (api1) return api1;

            // API 2: Prayer Times API
            const api2 = await this.tryPrayerTimesAPI(lat, lon, year, month, day);
            if (api2) return api2;

            // API 3: IslamicFinder API
            const api3 = await this.tryIslamicFinderAPI(lat, lon, year, month, day);
            if (api3) return api3;

            throw new Error('Semua API gagal');

        } catch (error) {
            throw new Error(`Gagal mendapatkan jadwal sholat: ${error.message}`);
        }
    }

    async tryAladhanAPI(lat, lon, year, month, day, method) {
        try {
            const response = await this.axiosInstance.get(
                `http://api.aladhan.com/v1/timings/${day}-${month}-${year}`,
                {
                    params: {
                        latitude: lat,
                        longitude: lon,
                        method: method,
                        school: 1 // Shafi'i
                    }
                }
            );

            if (response.data && response.data.data) {
                const data = response.data.data;
                const timings = data.timings;

                return {
                    subuh: timings.Fajr,
                    syuruq: timings.Sunrise,
                    dzuhur: timings.Dhuhr,
                    ashar: timings.Asr,
                    maghrib: timings.Maghrib,
                    isya: timings.Isha,
                    metode: this.getMethodName(method),
                    sumber: 'Aladhan API'
                };
            }
        } catch (error) {
            console.log('Aladhan API gagal');
        }
        return null;
    }

    async tryPrayerTimesAPI(lat, lon, year, month, day) {
        try {
            const response = await this.axiosInstance.get(
                `http://api.pray.zone/v2/times/today.json`,
                {
                    params: {
                        latitude: lat,
                        longitude: lon,
                        elevation: 0,
                        school: 1
                    }
                }
            );

            if (response.data && response.data.results) {
                const data = response.data.results.datetime[0].times;

                return {
                    subuh: data.Fajr,
                    syuruq: data.Sunrise,
                    dzuhur: data.Dhuhr,
                    ashar: data.Asr,
                    maghrib: data.Maghrib,
                    isya: data.Isha,
                    metode: 'Prayer Times API',
                    sumber: 'Prayer Zone'
                };
            }
        } catch (error) {
            console.log('Prayer Times API gagal');
        }
        return null;
    }

    async tryIslamicFinderAPI(lat, lon, year, month, day) {
        try {
            const response = await this.axiosInstance.get(
                `https://www.islamicfinder.us/index.php/api/prayer_times`,
                {
                    params: {
                        latitude: lat,
                        longitude: lon,
                        timezone: 'auto',
                        method: 5,
                        month: month,
                        year: year
                    }
                }
            );

            if (response.data && response.data.data) {
                const data = response.data.data[day - 1];

                return {
                    subuh: data.fajr,
                    syuruq: data.sunrise,
                    dzuhur: data.dhuhr,
                    ashar: data.asr,
                    maghrib: data.maghrib,
                    isya: data.isha,
                    metode: 'Islamic Finder',
                    sumber: 'IslamicFinder API'
                };
            }
        } catch (error) {
            console.log('IslamicFinder API gagal');
        }
        return null;
    }

    getMethodName(method) {
        const methods = {
            1: 'University of Islamic Sciences, Karachi',
            2: 'Islamic Society of North America',
            3: 'Muslim World League',
            4: 'Umm Al-Qura University, Makkah',
            5: 'Egyptian General Authority of Survey',
            6: 'Institute of Geophysics, University of Tehran',
            7: 'Gulf Region',
            8: 'Kuwait',
            9: 'Qatar',
            10: 'Majlis Ugama Islam Singapura',
            11: 'Union Organization islamic de France',
            12: 'Diyanet İşleri Başkanlığı, Turkey',
            13: 'Spiritual Administration of Muslims of Russia',
            14: 'Moonsighting Committee Worldwide'
        };
        return methods[method] || 'Standard';
    }

    getCalculationMethod(country) {
        const countryMethods = {
            'indonesia': 1,
            'malaysia': 1,
            'singapore': 10,
            'brunei': 1,
            'saudi arabia': 4,
            'egypt': 5,
            'turkey': 12,
            'iran': 6,
            'kuwait': 8,
            'qatar': 9,
            'uae': 7,
            'usa': 2,
            'canada': 2,
            'uk': 2,
            'france': 11,
            'germany': 2,
            'russia': 13
        };
        return countryMethods[country.toLowerCase()] || 1;
    }

    getNextPrayer(prayerTimes) {
        const now = new Date();
        const currentTime = now.getHours() * 60 + now.getMinutes();

        const prayers = [
            { name: 'Subuh', time: this.timeToMinutes(prayerTimes.subuh) },
            { name: 'Dzuhur', time: this.timeToMinutes(prayerTimes.dzuhur) },
            { name: 'Ashar', time: this.timeToMinutes(prayerTimes.ashar) },
            { name: 'Maghrib', time: this.timeToMinutes(prayerTimes.maghrib) },
            { name: 'Isya', time: this.timeToMinutes(prayerTimes.isya) }
        ];

        for (let prayer of prayers) {
            if (prayer.time > currentTime) {
                const minutesLeft = prayer.time - currentTime;
                return {
                    sholat_berikutnya: prayer.name,
                    waktu_tersisa: `${Math.floor(minutesLeft / 60)} jam ${minutesLeft % 60} menit`,
                    jam: prayerTimes[prayer.name.toLowerCase()]
                };
            }
        }

        return {
            sholat_berikutnya: 'Subuh',
            waktu_tersisa: 'Besok pagi',
            jam: prayerTimes.subuh
        };
    }

    timeToMinutes(timeStr) {
        const [time, period] = timeStr.split(' ');
        let [hours, minutes] = time.split(':').map(Number);
        
        // Handle AM/PM format
        if (period) {
            if (period.toUpperCase() === 'PM' && hours !== 12) {
                hours += 12;
            } else if (period.toUpperCase() === 'AM' && hours === 12) {
                hours = 0;
            }
        }
        
        return hours * 60 + minutes;
    }

    async getPrayerSchedule(city, country = '') {
        try {
            console.log(`📍 Mencari koordinat: ${city}${country ? ', ' + country : ''}`);
            
            const coordinates = await this.getCityCoordinates(city, country);
            const method = this.getCalculationMethod(country || 'indonesia');
            
            console.log(`🕌 Mendapatkan jadwal sholat...`);
            const prayerTimes = await this.getPrayerTimesByCoordinates(
                coordinates.lat, 
                coordinates.lon, 
                method
            );

            const nextPrayer = this.getNextPrayer(prayerTimes);

            return {
                success: true,
                lokasi: coordinates.display_name,
                kota: city,
                negara: country || 'Indonesia',
                tanggal: this.formatDate(),
                update: this.getCurrentTime(),
                koordinat: {
                    latitude: coordinates.lat,
                    longitude: coordinates.lon
                },
                metode_perhitungan: prayerTimes.metode,
                sumber: prayerTimes.sumber,
                jadwal: {
                    subuh: prayerTimes.subuh,
                    syuruq: prayerTimes.syuruq,
                    dzuhur: prayerTimes.dzuhur,
                    ashar: prayerTimes.ashar,
                    maghrib: prayerTimes.maghrib,
                    isya: prayerTimes.isya
                },
                sholat_berikutnya: nextPrayer
            };

        } catch (error) {
            return {
                success: false,
                error: error.message
            };
        }
    }
}

class SimpleGlobalPrayerTime {
    constructor() {
        this.prayerTime = new GlobalPrayerTime();
    }

    async getSchedule(city, country = '') {
        try {
            if (!city || typeof city !== 'string') {
                return JSON.stringify({
                    success: false,
                    error: 'Nama kota tidak valid'
                }, null, 2);
            }

            const result = await this.prayerTime.getPrayerSchedule(city, country);
            return JSON.stringify(result, null, 2);

        } catch (error) {
            return JSON.stringify({
                success: false,
                error: error.message
            }, null, 2);
        }
    }
}

async function main() {
    const args = process.argv.slice(2);
    
    if (args.length === 0) {
        console.log(`
🌍 Jadwal Sholat Global
Usage: node sholat.js <kota> [negara]

Contoh:
  node sholat.js jakarta
  node sholat.js "kuala lumpur" malaysia
  node sholat.js mecca "saudi arabia"
  node sholat.js london uk
  node sholat.js "new york" usa
  node sholat.js tokyo japan
  node sholat.js cairo egypt
  node sholat.js istanbul turkey

Fitur:
  ✅ Seluruh kota di dunia
  ✅ Metode perhitungan sesuai negara
  ✅ Koordinat GPS akurat
  ✅ Sholat berikutnya + countdown
  ✅ Multiple API backup
        `);
        return;
    }

    const city = args[0];
    const country = args[1] || '';

    const prayerTime = new SimpleGlobalPrayerTime();

    try {
        const result = await prayerTime.getSchedule(city, country);
        console.log(result);
    } catch (error) {
        console.log(JSON.stringify({
            success: false,
            error: error.message
        }, null, 2));
    }
}

if (require.main === module) {
    main();
}

module.exports = { GlobalPrayerTime, SimpleGlobalPrayerTime };