Praytime tracks iqamah times published on masjid websites.
Abu Hurairah (رضي الله عنه) reported: The Messenger of Allah (ﷺ) said, “A man’s Salat in congregation is twenty-five times more rewarding than his Salat at home or in his shop, and that is because when he performs his Wudu’ properly and proceeds towards the mosque with the purpose of performing Salat in congregation, he does not take a step without being raised a degree (in rank) for it and having a sin remitted for it, till he enters the mosque. When he is performing Salat, the angels continue to invoke Blessings of Allah on him as long as he is in his place of worship in a state of Wudu’. They say: 'O Allah! Have mercy on him! O Allah! Forgive him.' He is deemed to be engaged in Salat as long as he waits for it.”
https://abdurrahman.org/2014/09/04/riyad-us-saliheen-imaam-nawawi-chapter-191/
Prayer times are scraped on a nightly basis and saved in Firestore. In addition to prayer times, every masjid has lat/lng coordinates, timezone, and other metadata stored.
Web scraping is accomplished primarily with Cheerio if no client-side scripts are required to render the prayer times, otherwise Puppeteer is used.
The UI is a static webapp which uses the client-side Firestore JavaScript library to query nearby prayer times.
Each masjid has its own directory under lib.
Anybody can fork (make a copy of) this code repository, make changes, and submit those changes back to this repository.
- A unix environment (Linux, Mac osx, cygwin, etc)
- Node.js with npm
- A GitHub account for contributing changes back to the project, not necessary to run and test locally
This is the minimum needed to fork this repository and test crawlers locally.
- Fork, clone, or download this repo.
- Run
npm install
from thepraytime
directory. - Try running a crawler. Run the following command from the
praytime
dir:If all goes well, you should see output similar to this:script/run.sh ./lib/US/IL/islamic-center-of-naperville
starting ./lib/islamic-center-of-naperville {"uuid4":"d7c67298-6f4b-4694-a157-1ece31bc3294","crawlTime":"2018-07-26T02:31:21.696Z","name":"Islamic Center of Naperville","url":"https://islamiccenterofnaperville.org","address":"2844 West Ogden Ave, Naperville IL, 60540, USA","timeZoneId":"America/Chicago","placeId":"ChIJnw5viS74DogRlFBTHUQ89Dk","geo":{"latitude":41.753933,"longitude":-88.201616},"fajrIqama":"5:00 AM","zuhrIqama":"1:30 PM","asrIqama":"6:15 PM","maghribIqama":"8:23 PM","ishaIqama":"10:15 PM","juma1":"1:10 PM","juma2":"2:10 PM"} {"uuid4":"fefae38d-2e93-48fc-8bc2-6cb6f93a964e","crawlTime":"2018-07-26T02:31:21.696Z","name":"ICN Al-Hidayah","url":"https://islamiccenterofnaperville.org","address":"450 Olesen Dr, Naperville, IL 60540, USA","placeId":"ChIJiYkXUXJXDogRpL27TOZv-ao","timeZoneId":"America/Chicago","geo":{"latitude":41.768289,"longitude":-88.120149},"fajrIqama":"4:34 AM","zuhrIqama":"1:30 PM","asrIqama":"6:15 PM","maghribIqama":"8:23 PM","ishaIqama":"10:15 PM","juma1":"1:10 PM","juma2":"2:10 PM"}
TODO
- uuid
- https://developers-dot-devsite-v2-prod.appspot.com/maps/documentation/utils/geocoder/
- address:
copy(document.evaluate('//*[@id="result-0"]/table/tbody/tr/td[2]/p[2]/strong/following-sibling::text()[1]', document, null, XPathResult.STRING_TYPE, null).stringValue.trim())
- lat/lng:
copy(document.evaluate('//*[@id="result-0"]/table/tbody/tr/td[2]/p[3]/strong/following-sibling::text()[1]', document, null, XPathResult.STRING_TYPE, null).stringValue.match(/[\-\d.]+,[\-\d.]+/)[0])
- placeid
copy(document.evaluate('//*[@id="details-result-0"]/p[3]/a', document, null, XPathResult.STRING_TYPE, null).stringValue.trim())
- all in one:
copy({ address: document.evaluate('//*[@id="result-0"]/table/tbody/tr/td[2]/p[2]/strong/following-sibling::text()[1]', document, null, XPathResult.STRING_TYPE, null).stringValue.trim(), geo: { latitude: Number(document.evaluate('//*[@id="result-0"]/table/tbody/tr/td[2]/p[3]/strong/following-sibling::text()[1]', document, null, XPathResult.STRING_TYPE, null).stringValue.match(/[-\d.]+,[-\d.]+/)[0].split(',')[0]), longitude: Number(document.evaluate('//*[@id="result-0"]/table/tbody/tr/td[2]/p[3]/strong/following-sibling::text()[1]', document, null, XPathResult.STRING_TYPE, null).stringValue.match(/[-\d.]+,[-\d.]+/)[0].split(',')[1]) }, placeId: document.evaluate('//*[@id="details-result-0"]/p[3]/a', document, null, XPathResult.STRING_TYPE, null).stringValue.trim() })
- address:
- timezone - https://time.is/
- date
- standardjs, editorconfig
- chrome dev tools
- selector vs xpath
- iframes
- regexs
- document common masjid website mistakes
- no address on website
- examples
- masjidal
- mohid
- masjidapps
- axios / cheerio
- selector based: mcc-silver-springs
- explanation of selector syntax: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors#Combinators
- element text matching:
- selector based: mcc-silver-springs
- mobile app
- notify when watched masjid times change
- calculate drive times and alert when its time to leave
https://github.com/praytime/praytime.app - praytime.app frontend