import { exec } from 'node:child_process'; import { overrideConsole } from 'nodejs-better-console'; import Eris from 'eris'; import { Command } from 'commander'; import { parse } from 'shell-quote'; import { botToken, botWhitelist, adbIp, adbPort } from './config.js'; overrideConsole(); const eris = new Eris( botToken, { intents: ['directMessages'] } ), adb = command => new Promise((resolve, reject) => exec( `adb -s ${adbIp}:${adbPort} shell ${command}`, ( error, stdout, stderr ) => { if(error || stderr) reject(error || stderr); else resolve(stdout); } )), handleCommand = async command => { const program = new Command(''); let response; program.exitOverride(); program.configureOutput({ writeOut: output => response = { output, isRaw: true }, writeErr: output => response = { output, isRaw: true } }); program .command('shell') .description('Execute arbitrary shell command') .argument('', 'Arbitrary shell command') .action(async command => { response = { output: await adb(command), isRaw: true } }); program .command('p') .description('Play/pause media') .action(() => adb('input keyevent 85')); program .command('play') .description('Play media') .action(() => adb('input keyevent 126')); program .command('pause') .description('Pause media') .action(() => adb('input keyevent 127')); program .command('spotify') .description('Launch Spotify') .action(() => adb('monkey -p com.spotify.music 1')); program .command('mpv') .description('Launch MPV') .argument('', 'Media URL') .action(url => adb(`am start -a android.intent.action.VIEW -d ${url} -t video/any is.xyz.mpv`)); try { await program.parseAsync( parse(command), { from: 'user' } ); } catch(error){ if(!error.code.startsWith?.('commander.')) throw error; } if(response?.output) response.output = response.output.replace(/\r/g, '').trim(); return response; }; eris.on( 'error', error => console.error(error) ); eris.on( 'messageCreate', async message => { const { guildID, author: { id: authorID }, channel: { id: channelID }, id: messageID, content } = message, reply = async (content, isCodeBlock) => { const lines = content.split('\n'); let chunk = isCodeBlock ? '```\n' : ''; for(let lineIndex = 0; lineIndex < lines.length; lineIndex++){ const line = lines[lineIndex] + '\n', canAddLine = chunk.length + line.length + (isCodeBlock ? 3 : 0) <= 2000; if(canAddLine) chunk += line; if(!canAddLine || lineIndex === lines.length - 1){ if(isCodeBlock) chunk += '```'; await eris.createMessage( channelID, { content: chunk, messageReference: { messageID } } ); chunk = `\`\`\`\n${line}`; } } }; if(message.author.bot) return; if( guildID || !botWhitelist.includes(authorID) ) return message.addReaction('❌'); await message.addReaction('⏳'); try { const { output, isRaw } = await handleCommand(content) || {}; if(output) await reply(output, isRaw); await message.addReaction('✅'); } catch(error){ console.error(error); await message.addReaction('❌'); } } ); (async () => { await Promise.all([ eris.connect(), new Promise(resolve => eris.once('ready', resolve)) ]); console.log('Ready'); })().catch(error => console.error(error));