filename filter and parse date

This commit is contained in:
mrbesen 2021-04-11 15:25:34 +02:00
parent d46579b73f
commit aae84eb047
Signed by: MrBesen
GPG Key ID: 596B2350DCD67504
9 changed files with 169 additions and 55 deletions

View File

@ -12,3 +12,15 @@ struct Filter {
protected: protected:
bool ignoreCase; bool ignoreCase;
}; };
inline void resetStream(std::istream& i = std::cin) {
i.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
constexpr bool isLetter(char in, char compare) {
return in == compare || in == std::toupper(compare);
}
constexpr bool isYes(char c) {
return isLetter(c, 'y');
}

View File

@ -9,6 +9,7 @@
#include "search.h" #include "search.h"
#include "textfilter.h" #include "textfilter.h"
#include "mediafilter.h"
static bool run = true; static bool run = true;
@ -24,6 +25,9 @@ std::map<std::string, Filter*> filterlist;
void loadFilter() { void loadFilter() {
filterlist.insert({"TextSearch", new TextFilter()}); filterlist.insert({"TextSearch", new TextFilter()});
filterlist.insert({"RegexSearch", new RegexFilter()}); filterlist.insert({"RegexSearch", new RegexFilter()});
filterlist.insert({"HasMedia", new HasMediaFilter()});
filterlist.insert({"Filename", new FilenameFilter()});
filterlist.insert({"RegexFilename", new RegexFilenameFilter()});
} }
void removeFilter() { void removeFilter() {
@ -33,10 +37,6 @@ void removeFilter() {
filterlist.clear(); filterlist.clear();
} }
inline void resetStream(std::istream& i = std::cin) {
i.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
Filter* chooseFilter(std::ostream& o, std::istream& istr) { Filter* chooseFilter(std::ostream& o, std::istream& istr) {
//print filter //print filter
uint32_t i = 0; uint32_t i = 0;
@ -58,6 +58,18 @@ Filter* chooseFilter(std::ostream& o, std::istream& istr) {
return templookup.at(choise); return templookup.at(choise);
} }
static void printResults(const Search* search, std::list<const Message*>& list) {
for(const Message* m : list) {
Log::Entry e = (Log::info << search->getShortChatname(m->senderid));
e << "@" << search->getShortChatname(m->chatid) << "[" << m->getDate() << "]> (" << m->messageid << ") ";
if(m->text.empty()) {
e << "<empty>";
} else {
e << m->text;
}
}
}
int main(int argc, const char** argv) { int main(int argc, const char** argv) {
Log::init(); Log::init();
Log::setConsoleLogLevel(Log::Level::TRACE); Log::setConsoleLogLevel(Log::Level::TRACE);
@ -111,11 +123,9 @@ int main(int argc, const char** argv) {
if(!run) break; if(!run) break;
if(c == 'y' || c == 'Y') { if(isYes(c)) {
//print results //print results
for(const Message* m : results) { printResults(search, results);
Log::info << search->getShortChatname(m->senderid) << "@" << search->getShortChatname(m->chatid) << "> (" << m->messageid << ") " << m->text;
}
} }
Log::info << "New Subfilter (y)? Clear Search (c)? Change current Filter (anykey)?"; Log::info << "New Subfilter (y)? Clear Search (c)? Change current Filter (anykey)?";
@ -123,7 +133,7 @@ int main(int argc, const char** argv) {
if(!run) break; if(!run) break;
if(c == 'y' || c == 'Y') { if(isYes(c)) {
//filter //filter
Search* subsearch = new Search(*search, &results); Search* subsearch = new Search(*search, &results);
@ -133,7 +143,7 @@ int main(int argc, const char** argv) {
//set new search //set new search
search = subsearch; search = subsearch;
} else if(c == 'c' || c == 'C') { } else if(isLetter(c, 'c')) {
//move to root search //move to root search
if(search != &rootsearch) { if(search != &rootsearch) {
delete search; delete search;

15
src/mediafilter.cpp Normal file
View File

@ -0,0 +1,15 @@
#include "mediafilter.h"
void HasMediaFilter::setup(std::ostream& o, std::istream& str) {
o << "Should the message have media?";
char c;
str >> c;
needMedia = isYes(c);
resetStream(str);
}
bool HasMediaFilter::filter(const Message& m) const {
return m.hasFile() == needMedia;
}

10
src/mediafilter.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include "filter.h"
struct HasMediaFilter : public Filter {
virtual void setup(std::ostream& o, std::istream& str);
virtual bool filter(const Message& m) const;
protected:
bool needMedia; // true = msg should have media; false = mmessage should not have media
};

View File

@ -1,5 +1,48 @@
#include "message.h" #include "message.h"
#include <Log.h>
#include <nlohmann/json.hpp>
#include <ctime>
static void readText(const json& t, std::string& out) {
if(t.is_null()) return;
if(t.is_string())
out = t;
if(t.is_array()) {
std::ostringstream buff;
for(const json& entr : t) {
if(entr.is_string())
buff << (const std::string&) entr;
else if(entr.contains("text"))
buff << (const std::string&) entr["text"];
}
out = buff.str();
}
}
Message::Message(const json& m, int64_t chatid) : chatid(chatid) {
if(m.contains("text")) {
readText(m["text"], text);
messageid = m["id"];
if(m.contains("file"))
filename = m["file"];
else if(m.contains("photo"))
filename = m["photo"];
if(m.contains("from_id") && m["from_id"].is_number_unsigned())
senderid = m["from_id"];
if(m.contains("date")) {
tm parsedTime;
::strptime(m["date"].get_ref<const std::string&>().c_str(), "%Y-%m-%dT%T", &parsedTime);
date = timegm(&parsedTime);
}
isreply = m.contains("reply_to_message_id");
} else {
Log::warn << "text less message: " << m;
}
}
bool Message::operator==(const Message& m) const { bool Message::operator==(const Message& m) const {
return (m.chatid == chatid) && (m.messageid == messageid); return (m.chatid == chatid) && (m.messageid == messageid);
} }
@ -18,3 +61,12 @@ bool Message::operator<(const Message& m) const {
bool Message::hasFile() const { bool Message::hasFile() const {
return !filename.empty(); return !filename.empty();
} }
std::string Message::getDate() const {
struct tm buff;
static const uint32_t buffsize = 20;
char outbuff[buffsize];
gmtime_r(&date, &buff);
strftime(outbuff, buffsize, "%Y-%m-%d %T", &buff);
return std::string(outbuff);
}

View File

@ -1,17 +1,25 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include <string> #include <string>
#include <nlohmann/json_fwd.hpp>
using json = nlohmann::json;
struct Message { struct Message {
int64_t chatid; int64_t chatid = 0;
int64_t messageid; int64_t messageid = 0;
int64_t senderid; int64_t senderid = 0;
std::string text; std::string text = "";
std::string filename = ""; //empty filename = no file std::string filename = ""; //empty filename = no file
time_t date = 0;
bool isreply = false; bool isreply = false;
Message() {}
Message(const json& j, int64_t chatid);
bool operator==(const Message& m) const; bool operator==(const Message& m) const;
bool operator!=(const Message& m) const; bool operator!=(const Message& m) const;
bool operator<(const Message& m) const; bool operator<(const Message& m) const;
bool hasFile() const; bool hasFile() const;
std::string getDate() const;
}; };

View File

@ -125,43 +125,11 @@ void Search::runsearch(const Filter& filter, std::list<const Message*>& out) con
} }
} }
static void readText(const json& t, std::string& out) {
if(t.is_null()) return;
if(t.is_string())
out = t;
if(t.is_array()) {
std::ostringstream buff;
for(const json& entr : t) {
if(entr.is_string())
buff << (const std::string&) entr;
else if(entr.contains("text"))
buff << (const std::string&) entr["text"];
}
out = buff.str();
}
}
void Search::loadMessages(const json& j, int64_t chatid) { void Search::loadMessages(const json& j, int64_t chatid) {
uint32_t failed = 0; uint32_t failed = 0;
for(const json& m : j) { for(const json& m : j) {
try { try {
if(m.contains("text")) { deduplicate.insert({m, chatid}); // Message(const json&) constructor call
std::string text;
readText(m["text"], text);
std::string file = "";
if(m.contains("file"))
file = m["file"];
else if(m.contains("photo"))
file = m["photo"];
int64_t sender = 0;
if(m.contains("from_id") && m["from_id"].is_number_unsigned())
sender = m["from_id"];
deduplicate.insert({chatid, m["id"], sender, text, file, m.contains("reply_to_message_id")});
} else {
Log::warn << "text less message: " << m;
}
} catch(const nlohmann::detail::exception& e) { } catch(const nlohmann::detail::exception& e) {
Log::warn << "Parse error: " << e.id << " " << e.what(); Log::warn << "Parse error: " << e.id << " " << e.what();
} catch(...) { } catch(...) {

View File

@ -27,20 +27,45 @@ void TextFilter::setup(std::ostream& o, std::istream& str) {
} }
bool TextFilter::filter(const Message& m) const { bool TextFilter::filter(const Message& m) const {
return match(m.text);
}
bool TextFilter::match(const std::string& input) const {
if(ignoreCase) if(ignoreCase)
return matchesIC(m.text, text); return matchesIC(input, text);
else else
return matches(m.text, text); return matches(input, text);
} }
void RegexFilter::setup(std::ostream& o, std::istream& str) { void RegexFilter::setup(std::ostream& o, std::istream& str) {
//build regex pattern //build regex pattern
std::string text = ""; //TODO o << "Regexpattern: " << std::endl;
std::string text;
getline(str, text);
pattern = std::regex(text, (ignoreCase ? std::regex::icase : (std::regex::flag_type) 0)); pattern = std::regex(text, (ignoreCase ? std::regex::icase : (std::regex::flag_type) 0));
Filter::setup(o, str); Filter::setup(o, str);
} }
bool RegexFilter::filter(const Message& m) const { bool RegexFilter::filter(const Message& m) const {
return std::regex_search(m.text, pattern); return match(m.text);
}
bool RegexFilter::match(const std::string& input) const {
return std::regex_search(input, pattern);
}
bool FilenameFilter::filter(const Message& m) const {
if(m.hasFile()) {
return match(m.filename);
}
return false;
}
bool RegexFilenameFilter::filter(const Message& m) const {
if(m.hasFile()) {
return match(m.filename);
}
return false;
} }

View File

@ -10,6 +10,8 @@ struct TextFilter : public Filter {
virtual void setup(std::ostream& o, std::istream& str) override; virtual void setup(std::ostream& o, std::istream& str) override;
virtual bool filter(const Message& m) const override; virtual bool filter(const Message& m) const override;
protected: protected:
virtual bool match(const std::string& input) const;
std::string text; std::string text;
}; };
@ -17,5 +19,17 @@ struct RegexFilter : public Filter {
virtual void setup(std::ostream& o, std::istream& str) override; virtual void setup(std::ostream& o, std::istream& str) override;
virtual bool filter(const Message& m) const override; virtual bool filter(const Message& m) const override;
protected: protected:
virtual bool match(const std::string& input) const;
std::regex pattern; std::regex pattern;
}; };
struct FilenameFilter : public TextFilter {
//virtual void setup(std::ostream& o, std::istream& str) override;
virtual bool filter(const Message& m) const override;
};
struct RegexFilenameFilter : public RegexFilter {
//virtual void setup(std::ostream& o, std::istream& str) override;
virtual bool filter(const Message& m) const override;
};