<commit_before>#include <algorithm>
#include <ctime>
#include <cpr/cpr.h>
#include <fstream>
#include <json/json.h>
#include <iostream>
#include <regex>
#include <sstream>
#include <utils.h>
#include "CommandHandler.h"
#include "ExpressionParser.h"
#include "OptionParser.h"
#include "SkillMap.h"
#include "version.h"

#define DEFAULT 1
#define CUSTOM 2

CommandHandler::CommandHandler(const std::string &name,
		const std::string &channel, Moderator *mod,
		URLParser *urlp, EventManager *evtp, Giveaway *givp)
	: m_name(name), m_channel(channel), m_modp(mod), m_parsep(urlp),
	m_customCmds(NULL), m_evtp(evtp), m_givp(givp), m_counting(false),
	m_gen(m_rd())
{
	/* initializing pointers to all default commands */
	m_defaultCmds["ehp"] = &CommandHandler::ehpFunc;
	m_defaultCmds["level"] = &CommandHandler::levelFunc;
	m_defaultCmds["lvl"] = &CommandHandler::levelFunc;
	m_defaultCmds["ge"] = &CommandHandler::geFunc;
	m_defaultCmds["calc"] = &CommandHandler::calcFunc;
	m_defaultCmds["cml"] = &CommandHandler::cmlFunc;
	m_defaultCmds["8ball"] = &CommandHandler::eightballFunc;
	m_defaultCmds["sp"] = &CommandHandler::strawpollFunc;
	m_defaultCmds["active"] = &CommandHandler::activeFunc;
	m_defaultCmds["uptime"] = &CommandHandler::uptimeFunc;
	m_defaultCmds["rsn"] = &CommandHandler::rsnFunc;
	m_defaultCmds["commands"] = &CommandHandler::commandsFunc;
	m_defaultCmds["help"] = &CommandHandler::helpFunc;
	m_defaultCmds["about"] = &CommandHandler::aboutFunc;
	m_defaultCmds["submit"] = &CommandHandler::submitFunc;
	m_defaultCmds[m_wheel.cmd()] = &CommandHandler::wheelFunc;

	m_defaultCmds["strawpoll"] = &CommandHandler::strawpollFunc;
	m_defaultCmds["count"] = &CommandHandler::countFunc;
	m_defaultCmds["whitelist"] = &CommandHandler::whitelistFunc;
	m_defaultCmds["permit"] = &CommandHandler::permitFunc;
	m_defaultCmds["addcom"] = &CommandHandler::makecomFunc;
	m_defaultCmds["editcom"] = &CommandHandler::makecomFunc;
	m_defaultCmds["delcom"] = &CommandHandler::delcomFunc;
	m_defaultCmds["addrec"] = &CommandHandler::addrecFunc;
	m_defaultCmds["delrec"] = &CommandHandler::delrecFunc;
	m_defaultCmds["listrec"] = &CommandHandler::listrecFunc;
	m_defaultCmds["setrec"] = &CommandHandler::setrecFunc;
	m_defaultCmds["setgiv"] = &CommandHandler::setgivFunc;

	m_customCmds = new CustomCommandHandler(&m_defaultCmds, &m_cooldowns,
			m_wheel.cmd());
	if (!m_customCmds->isActive()) {
		std::cerr << " Custom commands will be disabled "
			"for this session." << std::endl;
		std::cin.get();
	}

	/* read all responses from file */
	m_responding = utils::readJSON("responses.json", m_responses);
	if (m_responding) {
		/* add response cooldowns to TimerManager */
		for (auto &val : m_responses["responses"])
			m_cooldowns.add('_' + val["name"].asString(),
				val["cooldown"].asInt());
	} else {
		std::cerr << "Failed to read responses.json. "
			"Responses disabled for this session.";
		std::cin.get();
	}

	/* set all command cooldowns */
	for (auto &p : m_defaultCmds)
		m_cooldowns.add(p.first);
	m_cooldowns.add(m_wheel.name(), 10);

	/* read extra 8ball responses */
	std::string path = utils::configdir() + utils::config("8ball");
	std::ifstream reader(path);
	if (!reader.is_open()) {
		std::cerr << "could not read " + path << std::endl;
		return;
	}
	std::string line;
	while (std::getline(reader, line))
		m_eightballResponses.push_back(line);
	reader.close();

	populateHelp();
}

CommandHandler::~CommandHandler()
{
	delete m_customCmds;
}

std::string CommandHandler::processCommand(const std::string &nick,
	const std::string &fullCmd, bool privileges)
{
	std::string output = "";

	/* the command is the first part of the string up to the first space */
	std::string cmd = fullCmd.substr(0, fullCmd.find(' '));

	struct cmdinfo c;
	c.nick = nick;
	c.cmd = cmd;
	c.fullCmd = fullCmd;
	c.privileges = privileges;

	/* custom command */
	Json::Value *ccmd;

	switch (source(cmd)) {
	case DEFAULT:
		if (privileges || m_cooldowns.ready(cmd)) {
			output += (this->*m_defaultCmds[cmd])(&c);
			m_cooldowns.setUsed(cmd);
		} else {
			std::cout << "command is on cooldown: " << cmd
				<< std::endl << std::endl;
		}
		break;
	case CUSTOM:
		ccmd = m_customCmds->getCom(cmd);
		if (privileges || m_cooldowns.ready((*ccmd)["cmd"].asString())) {
			output += (*ccmd)["response"].asString();
			m_cooldowns.setUsed((*ccmd)["cmd"].asString());
		} else {
			std::cout << "command is on cooldown: " << cmd
				<< std::endl << std::endl;
		}
		break;
	default:
		std::cerr << "invalid command: " << cmd << std::endl
			<< std::endl;
		break;
	}

	return output;
}

std::string CommandHandler::processResponse(const std::string &message)
{
	if (!m_responding)
		return "";

	/* test the message against all response regexes */
	for (auto &val : m_responses["responses"]) {
		std::string name = '_' + val["name"].asString();<commit_msg>Whisper user if command is on cooldown or invalid<commit_after>#include <algorithm>
#include <ctime>
#include <cpr/cpr.h>
#include <fstream>
#include <json/json.h>
#include <iostream>
#include <regex>
#include <sstream>
#include <utils.h>
#include "CommandHandler.h"
#include "ExpressionParser.h"
#include "OptionParser.h"
#include "SkillMap.h"
#include "version.h"

#define DEFAULT 1
#define CUSTOM 2

CommandHandler::CommandHandler(const std::string &name,
		const std::string &channel, Moderator *mod,
		URLParser *urlp, EventManager *evtp, Giveaway *givp)
	: m_name(name), m_channel(channel), m_modp(mod), m_parsep(urlp),
	m_customCmds(NULL), m_evtp(evtp), m_givp(givp), m_counting(false),
	m_gen(m_rd())
{
	/* initializing pointers to all default commands */
	m_defaultCmds["ehp"] = &CommandHandler::ehpFunc;
	m_defaultCmds["level"] = &CommandHandler::levelFunc;
	m_defaultCmds["lvl"] = &CommandHandler::levelFunc;
	m_defaultCmds["ge"] = &CommandHandler::geFunc;
	m_defaultCmds["calc"] = &CommandHandler::calcFunc;
	m_defaultCmds["cml"] = &CommandHandler::cmlFunc;
	m_defaultCmds["8ball"] = &CommandHandler::eightballFunc;
	m_defaultCmds["sp"] = &CommandHandler::strawpollFunc;
	m_defaultCmds["active"] = &CommandHandler::activeFunc;
	m_defaultCmds["uptime"] = &CommandHandler::uptimeFunc;
	m_defaultCmds["rsn"] = &CommandHandler::rsnFunc;
	m_defaultCmds["commands"] = &CommandHandler::commandsFunc;
	m_defaultCmds["help"] = &CommandHandler::helpFunc;
	m_defaultCmds["about"] = &CommandHandler::aboutFunc;
	m_defaultCmds["submit"] = &CommandHandler::submitFunc;
	m_defaultCmds[m_wheel.cmd()] = &CommandHandler::wheelFunc;

	m_defaultCmds["strawpoll"] = &CommandHandler::strawpollFunc;
	m_defaultCmds["count"] = &CommandHandler::countFunc;
	m_defaultCmds["whitelist"] = &CommandHandler::whitelistFunc;
	m_defaultCmds["permit"] = &CommandHandler::permitFunc;
	m_defaultCmds["addcom"] = &CommandHandler::makecomFunc;
	m_defaultCmds["editcom"] = &CommandHandler::makecomFunc;
	m_defaultCmds["delcom"] = &CommandHandler::delcomFunc;
	m_defaultCmds["addrec"] = &CommandHandler::addrecFunc;
	m_defaultCmds["delrec"] = &CommandHandler::delrecFunc;
	m_defaultCmds["listrec"] = &CommandHandler::listrecFunc;
	m_defaultCmds["setrec"] = &CommandHandler::setrecFunc;
	m_defaultCmds["setgiv"] = &CommandHandler::setgivFunc;

	m_customCmds = new CustomCommandHandler(&m_defaultCmds, &m_cooldowns,
			m_wheel.cmd());
	if (!m_customCmds->isActive()) {
		std::cerr << " Custom commands will be disabled "
			"for this session." << std::endl;
		std::cin.get();
	}

	/* read all responses from file */
	m_responding = utils::readJSON("responses.json", m_responses);
	if (m_responding) {
		/* add response cooldowns to TimerManager */
		for (auto &val : m_responses["responses"])
			m_cooldowns.add('_' + val["name"].asString(),
				val["cooldown"].asInt());
	} else {
		std::cerr << "Failed to read responses.json. "
			"Responses disabled for this session.";
		std::cin.get();
	}

	/* set all command cooldowns */
	for (auto &p : m_defaultCmds)
		m_cooldowns.add(p.first);
	m_cooldowns.add(m_wheel.name(), 10);

	/* read extra 8ball responses */
	std::string path = utils::configdir() + utils::config("8ball");
	std::ifstream reader(path);
	if (!reader.is_open()) {
		std::cerr << "could not read " + path << std::endl;
		return;
	}
	std::string line;
	while (std::getline(reader, line))
		m_eightballResponses.push_back(line);
	reader.close();

	populateHelp();
}

CommandHandler::~CommandHandler()
{
	delete m_customCmds;
}

std::string CommandHandler::processCommand(const std::string &nick,
	const std::string &fullCmd, bool privileges)
{
	std::string output = "";

	/* the command is the first part of the string up to the first space */
	std::string cmd = fullCmd.substr(0, fullCmd.find(' '));

	struct cmdinfo c;
	c.nick = nick;
	c.cmd = cmd;
	c.fullCmd = fullCmd;
	c.privileges = privileges;

	/* custom command */
	Json::Value *ccmd;

	switch (source(cmd)) {
	case DEFAULT:
		if (privileges || m_cooldowns.ready(cmd)) {
			output += (this->*m_defaultCmds[cmd])(&c);
			m_cooldowns.setUsed(cmd);
		} else {
			output += "/w " + nick + " command is on cooldown: "
				+ cmd;
		}
		break;
	case CUSTOM:
		ccmd = m_customCmds->getCom(cmd);
		if (privileges || m_cooldowns.ready((*ccmd)["cmd"].asString())) {
			output += (*ccmd)["response"].asString();
			m_cooldowns.setUsed((*ccmd)["cmd"].asString());
		} else {
			output += "/w " + nick + " command is on cooldown: "
				+ cmd;
		}
		break;
	default:
		output += "/w " + nick + " not a bot command: " + cmd;
		break;
	}

	return output;
}

std::string CommandHandler::processResponse(const std::string &message)
{
	if (!m_responding)
		return "";

	/* test the message against all response regexes */
	for (auto &val : m_responses["responses"]) {
		std::string name = '_' + val["name"].asString();
{'fraction_non_alphanumeric': 0.16799091940976163, 'fraction_numerical': 0.0016510164069755444, 'mean_word_length': 5.898220640569395, 'pattern_counts': {'":': 0, '<': 65, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6400882', 'n_tokens_mistral': 3660, 'n_tokens_neox': 3585, 'n_words': 663}