Muthu Kumar
7 years ago
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 config = require('./config.js'); |
||||
|
const validator = require('./lib/validator'); |
||||
|
const responder = require('./lib/responseHandler.js'); |
||||
|
|
||||
|
const dateOptions = { |
||||
|
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.command('ls', |
||||
|
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); |
||||
|
}); |
||||
|
|
||||
const bot = new Telegraf(config.apiKey) |
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('start', ctx => { |
bot.command('kill', |
||||
return ctx.reply('Bot succesfully started!'); |
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.hears('hi', ctx => { |
bot.use(ctx => { |
||||
return ctx.reply('Hey!, How are you?'); |
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