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

@ -11,4 +11,16 @@ struct Filter {
virtual bool filter(const Message& m) const = 0;
protected:
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 "textfilter.h"
#include "mediafilter.h"
static bool run = true;
@ -24,6 +25,9 @@ std::map<std::string, Filter*> filterlist;
void loadFilter() {
filterlist.insert({"TextSearch", new TextFilter()});
filterlist.insert({"RegexSearch", new RegexFilter()});
filterlist.insert({"HasMedia", new HasMediaFilter()});
filterlist.insert({"Filename", new FilenameFilter()});
filterlist.insert({"RegexFilename", new RegexFilenameFilter()});
}
void removeFilter() {
@ -33,10 +37,6 @@ void removeFilter() {
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) {
//print filter
uint32_t i = 0;
@ -58,6 +58,18 @@ Filter* chooseFilter(std::ostream& o, std::istream& istr) {
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) {
Log::init();
Log::setConsoleLogLevel(Log::Level::TRACE);
@ -111,11 +123,9 @@ int main(int argc, const char** argv) {
if(!run) break;
if(c == 'y' || c == 'Y') {
if(isYes(c)) {
//print results
for(const Message* m : results) {
Log::info << search->getShortChatname(m->senderid) << "@" << search->getShortChatname(m->chatid) << "> (" << m->messageid << ") " << m->text;
}
printResults(search, results);
}
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(c == 'y' || c == 'Y') {
if(isYes(c)) {
//filter
Search* subsearch = new Search(*search, &results);
@ -133,7 +143,7 @@ int main(int argc, const char** argv) {
//set new search
search = subsearch;
} else if(c == 'c' || c == 'C') {
} else if(isLetter(c, 'c')) {
//move to root search
if(search != &rootsearch) {
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 <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 {
return (m.chatid == chatid) && (m.messageid == messageid);
}
@ -17,4 +60,13 @@ bool Message::operator<(const Message& m) const {
bool Message::hasFile() const {
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
#include <cstdint>
#include <string>
#include <nlohmann/json_fwd.hpp>
using json = nlohmann::json;
struct Message {
int64_t chatid;
int64_t messageid;
int64_t senderid;
std::string text;
int64_t chatid = 0;
int64_t messageid = 0;
int64_t senderid = 0;
std::string text = "";
std::string filename = ""; //empty filename = no file
time_t date = 0;
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 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) {
uint32_t failed = 0;
for(const json& m : j) {
try {
if(m.contains("text")) {
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;
}
deduplicate.insert({m, chatid}); // Message(const json&) constructor call
} catch(const nlohmann::detail::exception& e) {
Log::warn << "Parse error: " << e.id << " " << e.what();
} catch(...) {

View File

@ -27,20 +27,45 @@ void TextFilter::setup(std::ostream& o, std::istream& str) {
}
bool TextFilter::filter(const Message& m) const {
return match(m.text);
}
bool TextFilter::match(const std::string& input) const {
if(ignoreCase)
return matchesIC(m.text, text);
return matchesIC(input, text);
else
return matches(m.text, text);
return matches(input, text);
}
void RegexFilter::setup(std::ostream& o, std::istream& str) {
//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));
Filter::setup(o, str);
}
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 bool filter(const Message& m) const override;
protected:
virtual bool match(const std::string& input) const;
std::string text;
};
@ -17,5 +19,17 @@ struct RegexFilter : public Filter {
virtual void setup(std::ostream& o, std::istream& str) override;
virtual bool filter(const Message& m) const override;
protected:
virtual bool match(const std::string& input) const;
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;
};