diff --git a/ircbot.json b/ircbot.json index b0b3b87..75c8d87 100644 --- a/ircbot.json +++ b/ircbot.json @@ -12,16 +12,15 @@ { "logpath": "D:\\irc-log", "admin": "acetone", + "error": "ошибка", "find": "поиск", "notfound": "ничего не найдено.", "findzero": "а что искать?", "reloaded": "Конфиг перечитан.", - "help": "доступные команды: 'лог', 'поиск' и 'ссылки'.", + "help": "доступные команды: 'лог' и 'поиск'.", - "лог": "лог чата: http://acetone.i2p/doc/irc-log/ # http://[324:9de3:fea4:f6ac::ace]/doc/irc-log/ # http://acetonemadzhxzi2e5tomavam6xpucdfwn2g35vrsz6izgaxv5bmuhad.onion/doc/irc-log/", - "ссылки": "123", - "русский": "гордо" + "лог": "лог чата: 'поиск ГГГГ-ММ-ДД [слово]' # http://acetone.i2p/doc/irc-log/ # http://[324:9de3:fea4:f6ac::ace]/doc/irc-log/ # http://acetonemadzhxzi2e5tomavam6xpucdfwn2g35vrsz6izgaxv5bmuhad.onion/doc/irc-log/" } } diff --git a/main.cpp b/main.cpp index 5e3d543..a8ca7a0 100644 --- a/main.cpp +++ b/main.cpp @@ -14,15 +14,52 @@ std::string config_file = "ircbot.json"; TcpSyncClient * volatile tsc = nullptr; bool tsc_created = false; +#ifdef WIN32 + std::string slash = "\\"; +#else + std::string slash = "/"; +#endif + std::map conf = { { "admin" , "" }, + { "error" , "" }, { "logpath" , "" }, { "find" , "" }, { "notfound", "" }, { "findzero", "" } }; +std::vector search_detail(std::string date, std::string text) +{ + std::string year = date.substr(0, 4); // YYYY + std::string month = date.substr(year.size()+1, 2); // MM + std::string day = date.substr(year.size() + month.size() + 2, 2); // DD + std::vector result; + + std::cout << "[search_detail()] " << year << " - " << month << " - " << day << " * " << text << " *" << std::endl; + std::regex regex; + if (text != "") // Нужен не весь лог, а конкретные сообщения + { + std::regex r(".*" + text + ".*", std::regex_constants::extended | std::regex_constants::icase); + regex = r; + } + + std::string path = conf["logpath"] + slash + year + slash + month + slash + day + ".txt"; + if (! boost::filesystem::exists(path)) return result; + + std::ifstream log(path); + std::string buffer; + while(getline(log, buffer)) + { + if (text == "") result.push_back(buffer); + else if (std::regex_match(buffer, regex)) result.push_back(buffer); + } + log.close(); + + return result; +} + std::string search(std::string text) { constexpr int maxSize = 10; @@ -131,12 +168,6 @@ int write_log(std::string msg) std::ofstream out; -#ifdef WIN32 - std::string slash = "\\"; -#else - std::string slash = "/"; -#endif - if (boost::filesystem::exists(conf["logpath"])) { if (! boost::filesystem::exists(conf["logpath"] + slash + year + slash + month)) @@ -190,21 +221,47 @@ void handler() if(tsc->to_read) { // Есть сообщения, адресованные боту std::string msg = tsc->get_msg(); - if (tsc->get_msg_nick() == conf["admin"] && (msg.find("reload") == 0)) // Reload + if (tsc->get_msg_nick() == conf["admin"] && (msg.find("reload") == 0)) //// Reload { if (read_config()) tsc->write_to_channel(conf["reloaded"]); else tsc->write_to_channel("Ошибка."); } - else if (msg.find(conf["find"]) == 0) // Поиск + + else if (msg.find(conf["find"]) == 0) //// Поиск { + std::regex date_check(conf["find"] + " [0-9]{4}.[0-9]{2}.[0-9]{2}.*", std::regex_constants::egrep); + if (msg.find(' ') == std::string::npos) { tsc->write_to_channel(tsc->get_msg_nick() + ", " + conf["findzero"]); } - else { + else if (std::regex_match(msg, date_check)) { //// Запрос по дате + std::string pattern; + std::string date = msg.substr(conf["find"].size()+1, 10); // 10 == date size + + if (msg.substr(conf["find"].size()+11).find(' ') != std::string::npos) { // Поиск по слову + pattern = msg.substr(conf["find"].size() + date.size() + 2); + } + + std::vector result = search_detail(date, pattern); + + if (! result.empty()) + { + std::string nick = tsc->get_msg_nick(); + std::string header = date; + if (pattern != "") header += " # " + pattern; + tsc->write_to_user(nick, "[" + header + "]"); + + for (auto str: result) // Выдача основного ответа + { + tsc->write_to_user(nick, str); + } + } + else tsc->write_to_channel(tsc->get_msg_nick() + ", " + conf["error"]); + } + + else { //// Поиск с минимальной выдачей std::string target = msg.substr(conf["find"].size()+1); - while (target [target .size() - 1] == '\n'|| - target [target .size() - 1] == '\r') target.pop_back(); std::string result = search(target); if (result != "") { @@ -213,6 +270,7 @@ void handler() else tsc->write_to_channel(tsc->get_msg_nick() + ", " + conf["notfound"]); } } + else // Общий обработчик { handled = false; @@ -234,11 +292,10 @@ void handler() int res = write_log ("[" + tsc->get_raw_nick() + "] " + raw); if (res) { // Сообщение администратору об ошибке логирования - std::string report = "PRIVMSG " + conf["admin"] + - " Can't write to log. "; + std::string report = "Can't write to log. "; if (res == 1) report += "Can't open the file."; if (res == 2) report += "Logpath not found."; - tsc->write(report); + tsc->write_to_user(conf["admin"], report); } } std::this_thread::sleep_for(std::chrono::milliseconds(50)); diff --git a/tcpsyncclient.cpp b/tcpsyncclient.cpp index f8a2c21..029a4fc 100644 --- a/tcpsyncclient.cpp +++ b/tcpsyncclient.cpp @@ -48,8 +48,12 @@ bool TcpSyncClient::write(std::string msg) bool TcpSyncClient::write_to_channel(std::string msg) { - bool res = write("PRIVMSG " + params["channel"] + " " + msg); - return res; + return write("PRIVMSG " + params["channel"] + " " + msg); +} + +bool TcpSyncClient::write_to_user(std::string user, std::string msg) +{ + return write("PRIVMSG " + user + " " + msg); } std::string TcpSyncClient::get_msg() @@ -164,7 +168,8 @@ void TcpSyncClient::process_msg() if (msg.find("PRIVMSG " + params["channel"] + " :" + params["nickname"]) != std::string::npos) { m_msg = msg.substr(msg.find(" :" + params["nickname"]) + 3 + params["nickname"].size() ); - while (m_msg[0] == ' ') m_msg = m_msg.substr(1); // Режу первые пробелы + while (m_msg[0] == ' ') m_msg = m_msg.substr(1); + while (m_msg.back() == '\n'|| m_msg.back() == '\r' || m_msg.back() == ' ') m_msg.pop_back(); m_msg_nickname = msg.substr(1, msg.find('!') - 1); to_read = true; } @@ -176,8 +181,7 @@ void TcpSyncClient::process_msg() m_raw_nickname = msg.substr(1, msg.find('!') - 1); while (m_raw[0] == ' ') m_raw = m_raw.substr(1); - while (m_raw[m_raw.size() - 1] == '\n'|| - m_raw[m_raw.size() - 1] == '\r') m_raw.pop_back(); + while (m_raw.back() == '\n'|| m_raw.back() == '\r' || m_raw.back() == ' ') m_raw.pop_back(); if (m_raw.find("ACTION") == 0) { m_raw = "-" + m_raw.substr(7); diff --git a/tcpsyncclient.h b/tcpsyncclient.h index f11b754..f8884fd 100644 --- a/tcpsyncclient.h +++ b/tcpsyncclient.h @@ -18,13 +18,14 @@ class TcpSyncClient { public: TcpSyncClient(boost::asio::io_service& s, std::string config); - void start(); // Запуск бота - bool write(std::string); // Написать в сокет - bool write_to_channel(std::string); // Написать в целевой чат - std::string get_msg(); // Ник сообщения боту - std::string get_msg_nick(); // Сообщение боту - std::string get_raw(); // Ник сообщения на канале - std::string get_raw_nick(); // Сообщение на канале + void start(); // Запуск бота + bool write(std::string); // Написать в сокет + bool write_to_user(std::string, std::string); // Написать пользователю + bool write_to_channel(std::string); // Написать в целевой чат + std::string get_msg(); // Ник сообщения боту + std::string get_msg_nick(); // Сообщение боту + std::string get_raw(); // Ник сообщения на канале + std::string get_raw_nick(); // Сообщение на канале ~TcpSyncClient(); bool to_read; // Индикаторы наличия информации для чтения