discord-home-cinema/main.js

229 lines
7.9 KiB
JavaScript
Raw Normal View History

2024-01-27 03:54:37 +00:00
import { exec } from 'node:child_process';
2022-07-11 09:34:15 +00:00
import { overrideConsole } from 'nodejs-better-console';
import Eris from 'eris';
2024-01-27 19:38:33 +00:00
import { Command, Argument } from 'commander';
import KeyEvent from 'keyevent.json' assert { type: 'json' };
2024-01-27 21:25:29 +00:00
import AsciiTable from 'ascii-table';
2024-01-27 03:54:37 +00:00
import { parse } from 'shell-quote';
2022-07-11 09:34:15 +00:00
import {
botToken,
2024-01-27 03:54:37 +00:00
botWhitelist,
adbIp,
adbPort
2022-07-11 09:34:15 +00:00
} from './config.js';
overrideConsole();
const
eris = new Eris(
botToken,
{ intents: ['directMessages'] }
2024-01-27 03:54:37 +00:00
),
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.replace(/\r/g, '').trim());
2024-01-27 03:54:37 +00:00
}
)),
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('<command>', 'Arbitrary shell command')
.action(async command => {
response = {
output: await adb(command),
isRaw: true
}
});
2024-01-27 19:38:33 +00:00
program
.command('home')
.alias('h')
.description('Go to home')
.action(() => adb(`input keyevent ${KeyEvent.KEYCODE_HOME}`));
program
.command('back')
.alias('b')
.description('Go back')
.action(() => adb(`input keyevent ${KeyEvent.KEYCODE_BACK}`));
2024-01-27 03:54:37 +00:00
program
.command('p')
.description('Play/pause media')
.action(() => adb(`input keyevent ${KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE}`));
2024-01-27 03:54:37 +00:00
program
.command('play')
.description('Play media')
.action(() => adb(`input keyevent ${KeyEvent.KEYCODE_MEDIA_PLAY}`));
2024-01-27 03:54:37 +00:00
program
.command('pause')
.description('Pause media')
.action(() => adb(`input keyevent ${KeyEvent.KEYCODE_MEDIA_PAUSE}`));
2024-01-27 19:38:33 +00:00
program
.command('prev')
.description('Previous media')
.action(() => adb(`input keyevent ${KeyEvent.KEYCODE_MEDIA_PREVIOUS}`));
program
.command('next')
.description('Next media')
.action(() => adb(`input keyevent ${KeyEvent.KEYCODE_MEDIA_NEXT}`));
program
.command('type')
.description('Type text')
.argument('<text>', 'Text to type')
.action(text => adb(`input text ${text}`));
program
.command('press')
.description('Press key')
.addArgument(
new Argument('<key>', 'Key to press')
2024-01-27 23:05:45 +00:00
.choices(['tab', 'enter'])
2024-01-27 19:38:33 +00:00
)
.action(key => adb(`input keyevent ${{
'tab': KeyEvent.KEYCODE_TAB,
'enter': KeyEvent.KEYCODE_ENTER
}[key]}`));
2024-01-27 03:54:37 +00:00
program
.command('spotify')
.description('Launch Spotify')
.action(() => adb('monkey -p com.spotify.music 1'));
program
.command('mpv')
.description('Launch MPV')
.argument('<url>', 'Media URL')
.action(url => adb(`am start -a android.intent.action.VIEW -d ${url} -t video/any is.xyz.mpv`));
2024-01-27 19:38:33 +00:00
program
.command('kiwi')
.description('Launch Kiwi browser')
.argument('<url>', 'Website URL')
.action(url => adb(`am start -a android.intent.action.VIEW -d ${url} -t text/plain com.kiwibrowser.browser`));
2024-01-27 21:25:29 +00:00
program
.command('notifications')
.description('Show notification history')
.action(async () => {
const items = [];
let item;
for(let line of (await adb('dumpsys notification --noredact')).split('\n')){
line = line.trim();
if(line.startsWith('NotificationRecord('))
items.push(item = { app: line.slice(35).split(' ')[0] });
if(line.startsWith('android.title='))
item.title = line.slice(line.indexOf('(') + 1, -1);
if(line.startsWith('android.text='))
item.text = line.slice(line.indexOf('(') + 1, -1);
if(line.startsWith('mCreationTimeMs='))
item.date = parseInt(line.slice(16));
}
items.sort((a, b) => b.date - a.date);
response = {
output: new AsciiTable()
.setHeading('App', 'Time', 'Content')
.addRowMatrix(items
.sort((a, b) => b.date - a.date)
.map(item => [
item.app,
new Date(item.date).toLocaleTimeString(),
`${item.title}${item.title.length + item.text.length < 50 ? ` · ${item.text}` : ''}`
])
).toString(),
isRaw: true
};
});
2024-01-27 03:54:37 +00:00
try {
await program.parseAsync(
parse(command),
{ from: 'user' }
);
}
catch(error){
if(!error.code.startsWith?.('commander.'))
throw error;
}
return response;
};
eris.on(
'error',
error => console.error(error)
);
2022-07-11 09:34:15 +00:00
eris.on(
'messageCreate',
async message => {
2024-01-27 03:54:37 +00:00
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;
2022-07-11 09:34:15 +00:00
if(
guildID
||
!botWhitelist.includes(authorID)
2024-01-27 03:54:37 +00:00
) 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('❌');
2022-07-11 09:34:15 +00:00
}
}
);
(async () => {
await Promise.all([
eris.connect(),
2024-01-27 22:51:29 +00:00
new Promise(resolve => eris.once('ready', resolve)),
new Promise(resolve => exec(`adb connect ${adbIp}:${adbPort}`, resolve))
2022-07-11 09:34:15 +00:00
]);
console.log('Ready');
})().catch(error => console.error(error));