forked from cyclic-software/starter-micro-api
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
1,004 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
require('dotenv').config() | ||
const app = require('express')() | ||
const { Telegraf } = require('telegraf') | ||
const { getPrayerTimes } = require('./utils') | ||
|
||
const bot = new Telegraf(process.env.TELEGRAM_BOT_TOKEN || ''); | ||
|
||
|
||
bot.start((ctx) => ctx.reply('Assalamualaikum, Welcome to Prayer Time Bot')); | ||
|
||
bot.help((ctx) => ctx.reply('Send me a sticker')); | ||
|
||
bot.hears('hi', (ctx) => ctx.reply('Hey there')); | ||
|
||
bot.command('hariini', async (ctx) => { | ||
const waktu = await getPrayerTimes("today", "JHR03") | ||
let str = '' | ||
waktu.prayerTime.map((time) => { | ||
Object.entries(time).forEach(([key, value]) => { | ||
str = str.concat(`${key}: ${value}\n`) | ||
}) | ||
}) | ||
ctx.reply(str) | ||
}); | ||
|
||
bot.launch(); | ||
|
||
process.once('SIGINT', () => bot.stop('SIGINT')); | ||
process.once('SIGTERM', () => bot.stop('SIGTERM')); | ||
|
||
app.get('/prayerTime', async (req, res) => { | ||
const { period, zone } = req.query | ||
const prayerTime = await getPrayerTimes(period, zone) | ||
res.json(prayerTime) | ||
}) | ||
|
||
app.listen(process.env.PORT || 3000, () => { | ||
console.log('--------server is ruuning on port', 3000) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"dependencies": { | ||
"axios": "^1.3.6", | ||
"dotenv": "^16.0.3", | ||
"express": "^4.18.2", | ||
"nodemon": "^2.0.22", | ||
"telegraf": "^4.12.2" | ||
}, | ||
"scripts": { | ||
"dev": "nodemon index" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
const axios = require('axios'); | ||
const https = require('https') | ||
|
||
const Period = { | ||
Today: 'today', | ||
Week: 'week', | ||
Month: 'month', | ||
Year: 'year', | ||
Duration: 'duration' | ||
} | ||
|
||
const getZones = () => { | ||
return new Promise((resolve, reject) => { | ||
const url = "https://www.e-solat.gov.my/index.php?siteId=24&pageId=24"; | ||
https.get(url, (res) => { | ||
let result = ''; | ||
res.on('data', (chunk) => { | ||
result += chunk; | ||
}); | ||
res.on('end', () => { | ||
const pattern = /<select id="inputZone" class="form-control">([\w\W]*?)<\/select>/; | ||
const matches = result.match(pattern); | ||
const pattern2 = /<optgroup([\w\W]*?)<\/optgroup>/g; | ||
const stateJson = matches[1].match(pattern2).reduce((acc, zone) => { | ||
const statePattern = /label="([\w\W]*?)"/; | ||
const state = zone.match(statePattern)[1]; | ||
|
||
const zonePattern = /<option.*?value='([\w\W]*?)'.*?>([\w\W]*?)<\/option>/g; | ||
const zonJson = Array.from(zone.matchAll(zonePattern)).reduce((acc, matches) => { | ||
const zonecode = matches[1]; | ||
const zonename = matches[2].replace(/<\/?[^>]+(>|$)/g, '').split(" - ")[1]; | ||
acc[zonecode] = zonename; | ||
return acc; | ||
}, {}); | ||
|
||
acc[state] = zonJson; | ||
return acc; | ||
}, {}); | ||
|
||
resolve(stateJson); | ||
}); | ||
}).on('error', (err) => { | ||
reject(new Error(err.message)); | ||
}); | ||
}); | ||
}; | ||
|
||
|
||
|
||
|
||
const parseQuery = async (period, zone) => { | ||
if (typeof period !== 'string' || typeof zone !== 'string') throw new Error('period or zone must be a string') | ||
|
||
if (!Object.values(Period).includes(period)) throw new Error('period must be one of today, week, month, year, duration') | ||
|
||
let zones | ||
|
||
await getZones().then((stateJson) => { | ||
zones = stateJson | ||
}).catch((err) => { | ||
console.error(err); | ||
}); | ||
|
||
const stateKeys = Object.values(zones).map(i => Object.keys(i)).reduce((acc, curr) => [...acc, ...curr], []) | ||
if (!stateKeys.includes(zone)) throw new Error('invalid state key') | ||
|
||
return { | ||
period, | ||
zone | ||
} | ||
} | ||
|
||
const getPrayerTimes = async (period = Period.Today, zone) => { | ||
await parseQuery(period, zone) | ||
const url = `https://www.e-solat.gov.my/index.php?r=esolatApi/takwimsolat&period=${period}&zone=${zone}`; | ||
const res = await axios.post(url, | ||
{ datestart: 'YYYY-MM-DD', dateend: 'YYYY-MM-DD' } | ||
).then(response => response.data) | ||
.catch(error => console.error(error)); | ||
return res | ||
} | ||
|
||
module.exports = { | ||
Period, | ||
parseQuery, | ||
getPrayerTimes, | ||
getZones | ||
} |
Oops, something went wrong.