Simp-O-Matic

Dumb Discord bot in TS.
git clone git://git.knutsen.co/Simp-O-Matic
Log | Files | Refs | README | LICENSE

code.ts (2470B)


import { readFileSync as read_file } from 'fs';
import path from 'path';

import git from 'nodegit';

import { FORMATS } from '../extensions';
import { glue_strings } from '../utils';

const GIT_DIR = path.resolve(process.cwd(), "./.git");

type Authors = Record<string, number>;

const file_authors = async (filename: string): Promise<Authors> => {
	const authors = <Authors>{};

	const repo = await git.Repository.open(GIT_DIR);
	const blame = await git.Blame.file(repo, filename, ['p']);

	for (let i = 0; i < blame.getHunkCount(); i++) {
		// Hunk has bad type signatures, someone should tell `nodegit'.
		const hunk: any = blame.getHunkByIndex(i);
		const oid = hunk.finalCommitId();
		const commit = await repo.getCommit(oid);
		const name = commit.author().name();

		if (authors.hasOwnProperty(name)) authors[name] += 1;
		else                              authors[name]  = 1;
	}

	return authors;
};


export default async (homescope : HomeScope) => {
	const { message, args, CONFIG } = homescope;
	const p = CONFIG.commands.prefix;

	if (args.length < 1)
		return message.reply('Please provide a command to introspect.');

	const command = args[0].startsWith(p) ? args[0].tail() : args[0];

	if (command.match(/\//g))
		return message.reply("No paths allowed...");

	const expansion = CONFIG.commands.aliases[command];
	if (expansion) return message.channel.send(`\`${p}${command}\``
		+ ` is an alias that expands to \`${p}${expansion}\`.`);

	const filename = `lib/commands/${command}.ts`;

	try {
		const source = read_file(`${process.cwd()}/${filename}`)
			.toString();
		const authors = await file_authors(filename);
		const author_str = "\n**Author(s)**: " + Object.keys(authors)
			.map(author => `(\`${authors[author]}\`) ${author}`)
			.join(', ');

		const msg = `Source code for \`${p}${command}\`:\n`;

		const msg_len = [msg, source, author_str]
			.reduce((acc, s) => acc + s.length, 0);

		if (msg_len > 1990) {
			const chunks = glue_strings(source.split(/^/m), 1950);

			message.channel.send(msg);
			for (const chunk of chunks)
				message.channel.send(
					chunk.format(FORMATS.code_block, 'typescript'));
			message.channel.send(author_str);
		} else {
			message.channel.send(msg
				+ source.format(FORMATS.code_block, 'typescript')
				+ author_str);
		}
	} catch (error) {
		console.log(`Error in code.ts: ${error}`);
		message.reply(`Source for \`${p}${command}\``
			+ ` (\`${process.cwd()}/${filename}\`), was not found.`);
	}
};