const http = require('http') const express = require('express') const WebSocket = require('ws') const bodyParser = require('body-parser') const cookieParser = require('cookie-parser') const cookie = require('cookie') const crypto = require('crypto') const bot = require('./apps/bot') const log = require('./include/log') const adminapp = require('./apps/admin') const miniapp = require('./apps/miniapp') BigInt.prototype.toJSON = function () { return Number(this) } const app = express() const server = http.createServer(app) const wss = new WebSocket.Server({ server }) app.use(bodyParser.json({limit: '10mb'})) app.use(cookieParser()) app.use((req, res, next) => { const start = Date.now() const end = res.end res.end = function (chunk, encoding) { log.http (req, res, Date.now() - start) end.apply (res, arguments) } next() }) app.use((req, res, next) => { if(!(req.body instanceof Object)) return next() const escapeHtml = str => str.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, ''') Object .keys(req.body || {}) .filter(key => typeof(req.body[key]) == 'string' && key != 'password') .map(key => req.body[key] = escapeHtml(req.body[key])) next() }) app.post('(/api/admin/auth/telegram|/api/miniapp/auth)', (req, res, next) => { const data = Object.assign({}, req.query) delete data.hash const BOT_TOKEN = process.env.BOT_TOKEN || '7236504417:AAGVaodw3cRwGlf-jAhwnYb51OHaXcgpW8k' const dataCheckString = Object.keys(data).sort().map((key) => `${key}=${data[key]}`).join('\n') const secretKey = crypto.createHmac('sha256', 'WebAppData').update(BOT_TOKEN).digest() const hmac = crypto.createHmac('sha256', secretKey).update(dataCheckString).digest('hex') const timeDiff = Date.now() / 1000 - data.auth_date if (hmac !== req.query?.hash) // || timeDiff > 10) throw Error('ACCESS_DENIED::401') const user = JSON.parse(req.query.user) res.locals.telegram_id = user.id res.locals.start_param = req.query.start_param if (!res.locals.telegram_id) throw Error('ACCESS_DENIED::500') next() }) app.use('/api/admin', adminapp.router) app.use('/api/miniapp', miniapp.router) app.use((err, req, res, next) => { console.error(`Error for ${req.path}: ${err}`) log.error(err) let message, code [message, code = 500] = err.message.split('::') res.status(+code).json({success: false, error: { message, code}}) }) wss.on('connection', (ws, req) => { const sid = cookie.parse(req.headers.cookie || '')?.sid if (!miniapp.registerWS(sid, ws) && !adminapp.registerWS(sid, ws)) return ws.close(1008, 'Unauthorized') }) const PORT = process.env.PORT || 3000 server.listen(PORT, async () => { console.log(`Listening at port ${PORT}`) bot.start( +(process.env.API_ID || 26746106), process.env.API_HASH || '29e5f83c04e635fa583721473a6003b5', process.env.BOT_TOKEN || '7236504417:AAGVaodw3cRwGlf-jAhwnYb51OHaXcgpW8k', process.env.BOT_SID || '' ) })