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