5 changed files with 134 additions and 9 deletions
			
			
		@ -1,14 +1,92 @@ | 
				
			|||||
 | 
					const { spawn } = require('child_process'); | 
				
			||||
 | 
					const { EOL } = require('os'); | 
				
			||||
 | 
					
 | 
				
			||||
const Telegraf = require('telegraf'); | 
					const Telegraf = require('telegraf'); | 
				
			||||
const config = require('./config') | 
					const { path } = require('./util/index.js'); | 
				
			||||
 | 
					
 | 
				
			||||
const bot = new Telegraf(config.apiKey) | 
					const config = require('./config.js'); | 
				
			||||
 | 
					const validator = require('./lib/validator'); | 
				
			||||
 | 
					const responder = require('./lib/responseHandler.js'); | 
				
			||||
 | 
					
 | 
				
			||||
bot.command('start', ctx => { | 
					const dateOptions = { | 
				
			||||
	return ctx.reply('Bot succesfully started!'); | 
						weekday: 'long', | 
				
			||||
}) | 
						year: 'numeric', | 
				
			||||
 | 
						month: 'long', | 
				
			||||
 | 
						day: 'numeric', | 
				
			||||
 | 
						hour: 'numeric', | 
				
			||||
 | 
						minute: 'numeric', | 
				
			||||
 | 
					}; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					const bot = new Telegraf(config.botApiKey); | 
				
			||||
 | 
					const sessions = []; | 
				
			||||
 | 
					sessions.history = []; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					bot.use((ctx, next) =>  | 
				
			||||
 | 
						validator(ctx) | 
				
			||||
 | 
							.then(next) | 
				
			||||
 | 
							.catch(responder.fail( | 
				
			||||
 | 
								`Username Not authenticated!` | 
				
			||||
 | 
							))); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					bot.command('start', | 
				
			||||
 | 
						ctx => { | 
				
			||||
 | 
							ctx.replyWithHTML('Welcome to tsh -- <code>Telegram Shell!</code>'); | 
				
			||||
 | 
							const newProc = spawn('bash', { | 
				
			||||
 | 
								cwd: '/home' | 
				
			||||
 | 
							}); | 
				
			||||
 | 
							newProc.stdout.setEncoding('utf8'); | 
				
			||||
 | 
							sessions.push(newProc); | 
				
			||||
 | 
							sessions.currentSession = newProc; | 
				
			||||
 | 
						}); | 
				
			||||
 | 
					
 | 
				
			||||
bot.hears('hi', ctx => { | 
					bot.command('ls', | 
				
			||||
	return ctx.reply('Hey!, How are you?'); | 
						ctx => ctx.reply( | 
				
			||||
 | 
							sessions.reduce((acc, _, index) => | 
				
			||||
 | 
								acc ? `${acc}\n${index}` : `${index}`, '') | 
				
			||||
 | 
							|| `No sessions found. Start one with /start.` | 
				
			||||
 | 
						)); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					bot.command('attach', | 
				
			||||
 | 
						ctx => { | 
				
			||||
 | 
							const text = path(['update', 'message', 'text'], ctx); | 
				
			||||
 | 
							const sessionIndex = parseInt(text.replace('/attach ', '').trim()); | 
				
			||||
 | 
							if(Number.isNaN(sessionIndex) || !sessions[sessionIndex]) return responder.fail('Session not found. /ls for list of sessions')(ctx); | 
				
			||||
 | 
							sessions.currentSession = sessions[sessionIndex]; | 
				
			||||
 | 
							return responder.success(`Reattached to shell ${sessionIndex}`)(ctx); | 
				
			||||
 | 
						}); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					bot.command('detach', | 
				
			||||
 | 
						ctx => { | 
				
			||||
 | 
							const text = path(['update', 'message', 'text'], ctx); | 
				
			||||
 | 
							const sessionIndex = parseInt(text.replace('/detach ', '').trim()); | 
				
			||||
 | 
							const currentSession = text.trim() === '/detach' ? sessions.currentSession : sessions[sessionIndex]; | 
				
			||||
 | 
							if(!currentSession) return responder.fail('Session not found. /ls for list of sessions.')(ctx); | 
				
			||||
 | 
							sessions.currentSession = undefined; | 
				
			||||
 | 
							return responder.success(`Detached from shell ${sessionIndex}`)(ctx); | 
				
			||||
 | 
						}); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					bot.command('kill', | 
				
			||||
 | 
						ctx => { | 
				
			||||
 | 
							const text = path(['update', 'message', 'text'], ctx); | 
				
			||||
 | 
							const sessionIndex = parseInt(text.replace('/kill ', '').trim()); | 
				
			||||
 | 
							if(Number.isNaN(sessionIndex) || !sessions[sessionIndex]) return responder.fail('Session not found. /ls for list of sessions.')(ctx); | 
				
			||||
 | 
							const disconnect = sessions[sessionIndex]; | 
				
			||||
 | 
							delete sessions[sessionIndex]; | 
				
			||||
 | 
							if(disconnect === sessions.currentSession) sessions.currentSession = undefined; | 
				
			||||
 | 
							disconnect.kill(); | 
				
			||||
 | 
							ctx.reply('Session killed. /ls for list of sessions.') | 
				
			||||
	}) | 
						}) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					bot.use(ctx => { | 
				
			||||
 | 
						if(!sessions.currentSession) return responder.fail('No active session. Start one with /start or view list of sessions by sending /ls.')(ctx); | 
				
			||||
 | 
						const cmd = ctx.update.message.text; | 
				
			||||
 | 
						const history = `${new Date().toLocaleDateString('en-IN', dateOptions)}: ${cmd}`; | 
				
			||||
 | 
						sessions.history.push(history); | 
				
			||||
 | 
						console.log(history); | 
				
			||||
 | 
						sessions.currentSession.stdin.write(cmd + EOL); | 
				
			||||
 | 
						sessions.currentSession.stdout.on('data', d => responder.success(d)(ctx)); | 
				
			||||
 | 
						sessions.currentSession.stdout.on('error', e => responder.success(e)(ctx)); | 
				
			||||
 | 
					}); | 
				
			||||
 | 
					
 | 
				
			||||
bot.startPolling(); | 
					bot.startPolling(); | 
				
			||||
 | 
					console.log(`Polling for updates.`); | 
				
			||||
 | 
				
			|||||
@ -0,0 +1,3 @@ | 
				
			|||||
 | 
					const process = ctx => { | 
				
			||||
 | 
						const { text } = ctx.update.message; | 
				
			||||
 | 
					} | 
				
			||||
@ -0,0 +1,34 @@ | 
				
			|||||
 | 
					const success = response => ctx => response ? ctx.reply(response) : null; | 
				
			||||
 | 
					const { EOL } = require('os'); | 
				
			||||
 | 
					const { path } = require('../util/index.js'); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					const convertCtx = ctx => { | 
				
			||||
 | 
						const message = path(['update', 'message'], ctx); | 
				
			||||
 | 
						const { id, first_name, username, language_code } = path(['from'], message); | 
				
			||||
 | 
						const { text } = message; | 
				
			||||
 | 
						return JSON.stringify({ | 
				
			||||
 | 
							id, | 
				
			||||
 | 
							first_name, | 
				
			||||
 | 
							username, | 
				
			||||
 | 
							language_code, | 
				
			||||
 | 
							text, | 
				
			||||
 | 
						}, null, 2); | 
				
			||||
 | 
					}; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					const fail = response => ctx => { | 
				
			||||
 | 
						if(!response | 
				
			||||
 | 
							|| !path(['update', 'message'], ctx) | 
				
			||||
 | 
						) return; | 
				
			||||
 | 
						console.log( | 
				
			||||
 | 
							EOL, | 
				
			||||
 | 
							response, | 
				
			||||
 | 
							EOL, | 
				
			||||
 | 
							`With context: `, | 
				
			||||
 | 
							convertCtx(ctx), | 
				
			||||
 | 
						); | 
				
			||||
 | 
						return ctx.reply(response); | 
				
			||||
 | 
					}; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					module.exports = { | 
				
			||||
 | 
						success, fail, | 
				
			||||
 | 
					}; | 
				
			||||
@ -0,0 +1,10 @@ | 
				
			|||||
 | 
					const { path } = require('../util/index.js'); | 
				
			||||
 | 
					const config = require('../config.js'); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					const validate = | 
				
			||||
 | 
						ctx => { | 
				
			||||
 | 
							if(!path(['update', 'message', 'from', 'id'], ctx)) return Promise.reject(ctx); | 
				
			||||
 | 
							return (ctx.update.message.from.id === config.masterID) ? Promise.resolve(ctx) : Promise.reject(ctx); | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					module.exports = validate; | 
				
			||||
					Loading…
					
					
				
		Reference in new issue