filename filter and parse date
This commit is contained in:
parent
d46579b73f
commit
aae84eb047
12
src/filter.h
12
src/filter.h
|
@ -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');
|
||||||
|
}
|
||||||
|
|
30
src/main.cpp
30
src/main.cpp
|
@ -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
15
src/mediafilter.cpp
Normal 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
10
src/mediafilter.h
Normal 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
|
||||||
|
};
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
|
@ -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(...) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
|
@ -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;
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user