TelegramSearch/src/search.cpp

135 lines
3.1 KiB
C++

#include "search.h"
#include <fstream>
#include <Log.h>
#include <mrbesen.h>
#include <regex>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
Searchflags operator|=(Searchflags& lhs, const Searchflags sf) {
lhs = (Searchflags) ((uint32_t) lhs | (uint32_t) sf);
return lhs;
}
bool operator&(Searchflags& lhs, const Searchflags sf) {
return (bool) ((uint32_t) lhs & (uint32_t) sf);
}
Search::Search() {}
Search::~Search() {}
Searchflags Search::fromString(const std::string& str) {
Searchflags f = Searchflags::NONE;
for(char c : str) {
switch(c) {
case 'R':
case 'r':
f |= Searchflags::REGEX;
break;
case 'i':
case 'I':
f |= Searchflags::IGNORECASE;
break;
default:
break;
}
}
return f;
}
void Search::addFile(const std::string& file) {
//laden den datei
try {
std::ifstream fstream(file);
json j;
fstream >> j;
if(j.contains("messages")) {
chatnames.insert({j["id"], j["name"].get<std::string>()});
loadMessages(j["messages"], j["id"]);
}
} catch (nlohmann::detail::parse_error& e) {
Log::error << "Could not load File: " << e.what();
}
}
std::list<const Message*> Search::search(std::string text, Searchflags flags) const {
std::list<const Message*> out;
if(flags & Searchflags::REGEX) {
searchRegex(text, flags & Searchflags::IGNORECASE, out);
return out;
}
if(flags & Searchflags::IGNORECASE) {
//turn search to lower
mrbesen::util::toLower(text);
runsearch(text, &Search::matchesIC, out);
} else {
runsearch(text, &Search::matches, out);
}
return out;
}
const std::string& Search::getChatname(uint64_t id) const {
static const std::string UNKOWNCHAT = "<unknownchat>";
auto it = chatnames.find(id);
if(it == chatnames.end()) return UNKOWNCHAT;
return it->second;
}
std::string Search::getShortChatname(uint64_t id) const {
std::string chatname = getChatname(id);
if(chatname.size() > 14) {
return chatname.substr(0, 14);
}
return chatname;
}
void Search::searchRegex(const std::string& text, bool ignoreCase, std::list<const Message*>& out) const {
//build regex pattern
std::regex pattern(text, (ignoreCase ? std::regex::icase : (std::regex::flag_type) 0));
}
void Search::runsearch(const std::string& st, bool (Search::*checker)(const std::string& msg, const std::string& text) const, std::list<const Message*>& out) const {
for(const Message& m : msgs) {
if((this->*checker)(m.text, st)) {
out.push_back(&m);
}
}
}
bool Search::matches(const std::string& msg, const std::string& text) const {
//simpler contains check
return (msg.find(text) != std::string::npos);
}
bool Search::matchesIC(const std::string& msg, const std::string& text) const {
//turn compare string to lower
std::string lower;
mrbesen::util::toLower(msg, lower);
return (lower.find(text) != std::string::npos);
}
void Search::loadMessages(const json& j, uint64_t chatid) {
uint32_t failed = 0;
for(const json& m : j) {
try {
msgs.push_back({m["text"], chatid, m["id"]});
} catch(...) {
failed ++;
}
}
if(failed == 0) {
Log::info << "Messages Loaded";
} else {
Log::warn << failed << " Messages failed to load";
}
}