-
Notifications
You must be signed in to change notification settings - Fork 3
/
app.js
135 lines (118 loc) · 3.87 KB
/
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Internal
const { spawn } = require('child_process');
const { EOL } = require('os');
const os = require('os');
// Runtime
const runtime = {
home: os.homedir(),
hostname: os.hostname(),
username: os.userInfo().username,
shell: os.platform() === 'win32' ? 'cmd.exe' : 'bash',
sessions: [],
identifierState: 0,
history: [],
}
// Modules
const Telegraf = require('telegraf');
//Config
const config = require('./config.js');
// Lib
const validator = require('./lib/validator.js');
const responder = require('./lib/responseHandler.js');
const sessionFinder = require('./lib/sessionFinder.js');
const listeners = require('./lib/listeners.js');
// Utils
const { extractCommandText } = require('./util/index.js');
const dateOptions = {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
};
const bot = new Telegraf(config.botApiKey);
const getSession = sessionFinder(runtime.sessions);
// Validate bot's master
bot.use(validator);
bot.command('start',
ctx => {
const newProc = spawn(runtime.shell, {
cwd: runtime.home
});
const identifier = extractCommandText('start')(ctx);
if(identifier) newProc.identifier = identifier;
else newProc.identifier = runtime.identifierState;
newProc.index = runtime.identifierState;
runtime.sessions[runtime.identifierState] = newProc;
runtime.identifierState++;
runtime.currentSession = newProc;
listeners.add(runtime.currentSession, responder, ctx);
return responder.success(`Welcome to tsh -- <code>Telegram Shell!</code>\n\n`
+ `You are now connected to <code>${runtime.hostname}</code>`
+ ` as <strong>${runtime.username}</strong>.`,
{ mode: 'html' },
)(ctx);
});
bot.command('shell',
ctx => {
const shell = extractCommandText('shell')(ctx);
runtime.shell = shell;
return responder.success(`Shell changed to ${shell}.`)(ctx);
});
bot.command('save',
ctx => {
const identifier = extractCommandText('save')(ctx);
if(!identifier) return responder.fail('Need a valid identifier to save session.')(ctx);
runtime.currentSession.identifier = identifier;
return responder.success(
`Saved session <code>${identifier}</code>.`,
{ mode: 'html' }
)(ctx);
});
bot.command('ls',
ctx => ctx.reply(
runtime.sessions.reduce((acc, session) =>
acc ? `${acc}\n${session.identifier}` : `${session.identifier}`, '')
|| `No sessions found. Start one with /start.`
));
bot.command('attach',
ctx => {
const session = getSession(ctx)('attach');
if(!session)
return responder.fail('Session not found. /ls for list of sessions')(ctx);
runtime.currentSession = session;
listeners.add(runtime.currentSession, responder, ctx);
return responder.success(`Reattached to shell ${session.identifier}`)(ctx);
});
bot.command('detach',
ctx => {
const session = getSession(ctx)('detach') || runtime.currentSession;
if(!session)
return responder.fail('Session not found. /ls for list of sessions.')(ctx);
listeners.remove(session);
runtime.currentSession = undefined;
return responder.success(`Detached from shell ${session.identifier}`)(ctx);
});
bot.command('kill',
ctx => {
const session = getSession(ctx)('kill') || runtime.currentSession;
if(!session)
return responder.fail('Session not found. /ls for list of sessions.')(ctx);
session.kill();
delete runtime.sessions[session.index];
if(session === runtime.currentSession) runtime.currentSession = undefined;
ctx.reply('Session killed. /ls for list of sessions.')
})
bot.use(ctx => {
if(!runtime.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}`;
runtime.history.push(history);
console.log(history);
runtime.currentSession.stdin.write(cmd + EOL);
});
bot.startPolling();
console.log(`Polling for updates.`);