Skip to content

Commit 58e21d9

Browse files
committed
Merge branch 'master'
2 parents 5da4af2 + 4d64c95 commit 58e21d9

File tree

5 files changed

+1004
-0
lines changed

5 files changed

+1004
-0
lines changed

index.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
require('dotenv').config()
2+
const app = require('express')()
3+
const { Telegraf } = require('telegraf')
4+
const { getPrayerTimes } = require('./utils')
5+
6+
const bot = new Telegraf(process.env.TELEGRAM_BOT_TOKEN || '');
7+
8+
9+
bot.start((ctx) => ctx.reply('Assalamualaikum, Welcome to Prayer Time Bot'));
10+
11+
bot.help((ctx) => ctx.reply('Send me a sticker'));
12+
13+
bot.hears('hi', (ctx) => ctx.reply('Hey there'));
14+
15+
bot.command('hariini', async (ctx) => {
16+
const waktu = await getPrayerTimes("today", "JHR03")
17+
let str = ''
18+
waktu.prayerTime.map((time) => {
19+
Object.entries(time).forEach(([key, value]) => {
20+
str = str.concat(`${key}: ${value}\n`)
21+
})
22+
})
23+
ctx.reply(str)
24+
});
25+
26+
bot.launch();
27+
28+
process.once('SIGINT', () => bot.stop('SIGINT'));
29+
process.once('SIGTERM', () => bot.stop('SIGTERM'));
30+
31+
app.get('/prayerTime', async (req, res) => {
32+
const { period, zone } = req.query
33+
const prayerTime = await getPrayerTimes(period, zone)
34+
res.json(prayerTime)
35+
})
36+
37+
app.listen(process.env.PORT || 3000, () => {
38+
console.log('--------server is ruuning on port', 3000)
39+
})

package.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"dependencies": {
3+
"axios": "^1.3.6",
4+
"dotenv": "^16.0.3",
5+
"express": "^4.18.2",
6+
"nodemon": "^2.0.22",
7+
"telegraf": "^4.12.2"
8+
},
9+
"scripts": {
10+
"dev": "nodemon index"
11+
}
12+
}

utils/index.js

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
const axios = require('axios');
2+
const https = require('https')
3+
4+
const Period = {
5+
Today: 'today',
6+
Week: 'week',
7+
Month: 'month',
8+
Year: 'year',
9+
Duration: 'duration'
10+
}
11+
12+
const getZones = () => {
13+
return new Promise((resolve, reject) => {
14+
const url = "https://www.e-solat.gov.my/index.php?siteId=24&pageId=24";
15+
https.get(url, (res) => {
16+
let result = '';
17+
res.on('data', (chunk) => {
18+
result += chunk;
19+
});
20+
res.on('end', () => {
21+
const pattern = /<select id="inputZone" class="form-control">([\w\W]*?)<\/select>/;
22+
const matches = result.match(pattern);
23+
const pattern2 = /<optgroup([\w\W]*?)<\/optgroup>/g;
24+
const stateJson = matches[1].match(pattern2).reduce((acc, zone) => {
25+
const statePattern = /label="([\w\W]*?)"/;
26+
const state = zone.match(statePattern)[1];
27+
28+
const zonePattern = /<option.*?value='([\w\W]*?)'.*?>([\w\W]*?)<\/option>/g;
29+
const zonJson = Array.from(zone.matchAll(zonePattern)).reduce((acc, matches) => {
30+
const zonecode = matches[1];
31+
const zonename = matches[2].replace(/<\/?[^>]+(>|$)/g, '').split(" - ")[1];
32+
acc[zonecode] = zonename;
33+
return acc;
34+
}, {});
35+
36+
acc[state] = zonJson;
37+
return acc;
38+
}, {});
39+
40+
resolve(stateJson);
41+
});
42+
}).on('error', (err) => {
43+
reject(new Error(err.message));
44+
});
45+
});
46+
};
47+
48+
49+
50+
51+
const parseQuery = async (period, zone) => {
52+
if (typeof period !== 'string' || typeof zone !== 'string') throw new Error('period or zone must be a string')
53+
54+
if (!Object.values(Period).includes(period)) throw new Error('period must be one of today, week, month, year, duration')
55+
56+
let zones
57+
58+
await getZones().then((stateJson) => {
59+
zones = stateJson
60+
}).catch((err) => {
61+
console.error(err);
62+
});
63+
64+
const stateKeys = Object.values(zones).map(i => Object.keys(i)).reduce((acc, curr) => [...acc, ...curr], [])
65+
if (!stateKeys.includes(zone)) throw new Error('invalid state key')
66+
67+
return {
68+
period,
69+
zone
70+
}
71+
}
72+
73+
const getPrayerTimes = async (period = Period.Today, zone) => {
74+
await parseQuery(period, zone)
75+
const url = `https://www.e-solat.gov.my/index.php?r=esolatApi/takwimsolat&period=${period}&zone=${zone}`;
76+
const res = await axios.post(url,
77+
{ datestart: 'YYYY-MM-DD', dateend: 'YYYY-MM-DD' }
78+
).then(response => response.data)
79+
.catch(error => console.error(error));
80+
return res
81+
}
82+
83+
module.exports = {
84+
Period,
85+
parseQuery,
86+
getPrayerTimes,
87+
getZones
88+
}

0 commit comments

Comments
 (0)