Added new LogSQLite which keeps a side database containing the last time the server has seen an individual. Added new AutoReplay setting to disable the auto replay on connect. Made the replay command have the ability to be called with the amount of items max you want to have replayed.

This commit is contained in:
GRMrGecko 2015-03-12 13:48:01 -05:00
parent 9bf45a739c
commit cd4ceb6f47
3 changed files with 1396 additions and 99 deletions

View File

@ -37,8 +37,9 @@ public:
AddCommand("DatabaseName", static_cast<CModCommand::ModCmdFunc>(&CLogMySQL::DatabaseNameCommand), "[a-z0-9]+", "MySQL database name.");
AddCommand("Connect", static_cast<CModCommand::ModCmdFunc>(&CLogMySQL::ConnectCommand), "", "Reconnect to the MySQL database.");
AddCommand("Replay", static_cast<CModCommand::ModCmdFunc>(&CLogMySQL::ReplayCommand), "", "Play back the messages received.");
AddCommand("Replay", static_cast<CModCommand::ModCmdFunc>(&CLogMySQL::ReplayCommand), "[0-9]*", "Play back the messages received.");
AddCommand("ReplayAll", static_cast<CModCommand::ModCmdFunc>(&CLogMySQL::ReplayAllCommand), "[1|0]", "Replay all messages stored.");
AddCommand("AutoReplay", static_cast<CModCommand::ModCmdFunc>(&CLogMySQL::AutoReplayCommand), "[1|0]", "Replay on connect.");
AddCommand("LogLimit", static_cast<CModCommand::ModCmdFunc>(&CLogMySQL::LogLimitCommand), "[0-9]+", "Limit the amount of items to store into the log.");
AddCommand("LogLevel", static_cast<CModCommand::ModCmdFunc>(&CLogMySQL::LogLevelCommand), "[0-4]", "Log level.");
@ -130,7 +131,12 @@ public:
void ReplayCommand(const CString &sLine) {
CString sArgs = sLine.Token(1, true);
if (!sArgs.empty()) {
Replay(sArgs.ToInt());
} else {
Replay();
}
PutModule("Replayed");
}
@ -151,6 +157,23 @@ public:
PutModule("ReplayAll is "+now+"set to: "+status);
}
void AutoReplayCommand(const CString &sLine) {
CString sArgs = sLine.Token(1, true);
bool help = sArgs.Equals("HELP");
if (help) {
PutModule("On: Replay on connect.");
PutModule("Off: Require replay command to replay.");
} else if (!sArgs.empty()) {
autoReplay = sArgs.ToBool();
SetSetting("autoReplay", (autoReplay ? "1" : "0"));
}
CString status = (autoReplay ? "On" : "Off");
CString now = (sArgs.empty() || help ? "" : "now ");
PutModule("AutoReplay is "+now+"set to: "+status);
}
void LogLimitCommand(const CString &sLine) {
CString sArgs = sLine.Token(1, true);
bool help = sArgs.Equals("HELP");
@ -269,7 +292,7 @@ public:
} else {
PutModule("Nick ignore list contains:");
for (vector<CString>::iterator it=nickIgnoreList.begin(); it<nickIgnoreList.end(); it++) {
for (std::vector<CString>::iterator it=nickIgnoreList.begin(); it<nickIgnoreList.end(); it++) {
PutModule(*it);
}
}
@ -279,7 +302,7 @@ public:
} else {
PutModule("Channel ignore list contains:");
for (vector<CString>::iterator it=chanIgnoreList.begin(); it<chanIgnoreList.end(); it++) {
for (std::vector<CString>::iterator it=chanIgnoreList.begin(); it<chanIgnoreList.end(); it++) {
PutModule(*it);
}
}
@ -287,7 +310,7 @@ public:
void DoNotTrack(const CString &sLine) {
bool tracking = true;
for (vector<CClient *>::iterator it=doNotTrackClient.begin(); it<doNotTrackClient.end(); it++) {
for (std::vector<CClient *>::iterator it=doNotTrackClient.begin(); it<doNotTrackClient.end(); it++) {
if (*it==m_pClient) {
tracking = false;
break;
@ -339,7 +362,7 @@ public:
void *theRet = mysql_real_connect(database, host.c_str(), username.c_str(), password.c_str(), databaseName.c_str(), (unsigned int)strtoul(port.c_str(), NULL, 10), MYSQL_UNIX_ADDR, CLIENT_COMPRESS);
databaseConnected = (theRet==database);
if (databaseConnected) {
cout << "LogMySQL: Database connected.\n";
std::cout << "LogMySQL: Database connected.\n";
MYSQL_RES *settings = mysql_list_tables(database, "settings");
if (mysql_num_rows(settings)==0) {
@ -350,9 +373,10 @@ public:
mysql_stmt_close(statement);
SetSetting("replayAll","0");
SetSetting("autoReplay","1");
SetSetting("logLimit","1");
SetSetting("logLevel","1");
SetSetting("version","1");
SetSetting("version","2");
}
}
if (settings!=NULL)
@ -380,15 +404,24 @@ public:
if (ignorelist!=NULL)
mysql_free_result(ignorelist);
unsigned long version = strtoul(GetSetting("version").c_str(), NULL, 10);
if (version==0) {
SetSetting("version","1");
version = 1;
}
if (version==1) {
SetSetting("autoReplay","1");
SetSetting("version","2");
version = 2;
}
replayAll = atoi(GetSetting("replayAll").c_str());
autoReplay = atoi(GetSetting("autoReplay").c_str());
logLimit = strtoul(GetSetting("logLimit").c_str(), NULL, 10);
logLevel = atoi(GetSetting("logLevel").c_str());
unsigned long version = strtoul(GetSetting("version").c_str(), NULL, 10);
if (version==0)
SetSetting("version","1");
} else {
cout << "LogMySQL: Database unable to connect.\n";
std::cout << "LogMySQL: Database unable to connect.\n";
}
}
}
@ -419,28 +452,28 @@ public:
bind[0].buffer_type = MYSQL_TYPE_STRING;
bind[0].buffer = (void*)target.c_str();
bind[0].buffer_length = target.length();
bind[0].is_null = false;
bind[0].is_null = (my_bool *)0;
bind[1].buffer_type = MYSQL_TYPE_STRING;
bind[1].buffer = (void*)nick.c_str();
bind[1].buffer_length = nick.length();
bind[1].is_null = false;
bind[1].is_null = (my_bool *)0;
bind[2].buffer_type = MYSQL_TYPE_STRING;
bind[2].buffer = (void*)type.c_str();
bind[2].buffer_length = type.length();
bind[2].is_null = false;
bind[2].is_null = (my_bool *)0;
bind[3].buffer_type = MYSQL_TYPE_STRING;
bind[3].buffer = (void*)message.c_str();
bind[3].buffer_length = message.length();
bind[3].is_null = false;
bind[3].is_null = (my_bool *)0;
CString time = GetUNIXTime();
bind[4].buffer_type = MYSQL_TYPE_STRING;
bind[4].buffer = (void*)time.c_str();
bind[4].buffer_length = time.length();
bind[4].is_null = false;
bind[4].is_null = (my_bool *)0;
status = mysql_stmt_bind_param(statement, bind);
if (status!=0) {
@ -468,7 +501,7 @@ public:
if (dataCount!=1) {
mysql_free_result(result);
mysql_stmt_close(statement);
cout << "LogMySQL: We are only suppose to receive 1 field. We received the count of " << dataCount << " fields.\n";
std::cout << "LogMySQL: We are only suppose to receive 1 field. We received the count of " << dataCount << " fields.\n";
return;
}
MYSQL_FIELD *fields = mysql_fetch_fields(result);
@ -526,7 +559,7 @@ public:
if (dataCount!=1) {
mysql_free_result(result);
mysql_stmt_close(statement);
cout << "LogMySQL: We are only suppose to receive 1 field. We received the count of " << dataCount << " fields.\n";
std::cout << "LogMySQL: We are only suppose to receive 1 field. We received the count of " << dataCount << " fields.\n";
return;
}
fields = mysql_fetch_fields(result);
@ -563,7 +596,7 @@ public:
bind2[0].buffer_type = MYSQL_TYPE_STRING;
bind2[0].buffer = (void*)rowid.c_str();
bind2[0].buffer_length = rowid.length();
bind2[0].is_null = false;
bind2[0].is_null = (my_bool *)0;
status = mysql_stmt_bind_param(statement2, bind2);
if (status!=0) {
@ -592,7 +625,7 @@ public:
bind[0].buffer_type = MYSQL_TYPE_STRING;
bind[0].buffer = (void*)name.c_str();
bind[0].buffer_length = name.length();
bind[0].is_null = false;
bind[0].is_null = (my_bool *)0;
status = mysql_stmt_bind_param(statement, bind);
if (status==0) {
@ -617,12 +650,12 @@ public:
bind[0].buffer_type = MYSQL_TYPE_STRING;
bind[0].buffer = (void*)value.c_str();
bind[0].buffer_length = value.length();
bind[0].is_null = false;
bind[0].is_null = (my_bool *)0;
bind[1].buffer_type = MYSQL_TYPE_STRING;
bind[1].buffer = (void*)name.c_str();
bind[1].buffer_length = name.length();
bind[1].is_null = false;
bind[1].is_null = (my_bool *)0;
status = mysql_stmt_bind_param(statement, bind);
if (status!=0) {
@ -643,12 +676,12 @@ public:
bind[0].buffer_type = MYSQL_TYPE_STRING;
bind[0].buffer = (void*)name.c_str();
bind[0].buffer_length = name.length();
bind[0].is_null = false;
bind[0].is_null = (my_bool *)0;
bind[1].buffer_type = MYSQL_TYPE_STRING;
bind[1].buffer = (void*)value.c_str();
bind[1].buffer_length = value.length();
bind[1].is_null = false;
bind[1].is_null = (my_bool *)0;
status = mysql_stmt_bind_param(statement, bind);
if (status!=0) {
@ -673,7 +706,7 @@ public:
bind[0].buffer_type = MYSQL_TYPE_STRING;
bind[0].buffer = (void*)name.c_str();
bind[0].buffer_length = name.length();
bind[0].is_null = false;
bind[0].is_null = (my_bool *)0;
status = mysql_stmt_bind_param(statement, bind);
if (status!=0) {
@ -691,7 +724,7 @@ public:
if (dataCount!=1) {
mysql_free_result(result);
mysql_stmt_close(statement);
cout << "LogMySQL: Settings are only suppose to return 1 as the field count. We received the count of " << dataCount << " fields.\n";
std::cout << "LogMySQL: Settings are only suppose to return 1 as the field count. We received the count of " << dataCount << " fields.\n";
return stringValue;
}
MYSQL_FIELD *fields = mysql_fetch_fields(result);
@ -816,12 +849,12 @@ public:
bind[0].buffer_type = MYSQL_TYPE_STRING;
bind[0].buffer = (void*)type.c_str();
bind[0].buffer_length = type.length();
bind[0].is_null = false;
bind[0].is_null = (my_bool *)0;
bind[1].buffer_type = MYSQL_TYPE_STRING;
bind[1].buffer = (void*)target.c_str();
bind[1].buffer_length = target.length();
bind[1].is_null = false;
bind[1].is_null = (my_bool *)0;
status = mysql_stmt_bind_param(statement, bind);
if (status!=0) {
@ -853,12 +886,12 @@ public:
bind[0].buffer_type = MYSQL_TYPE_STRING;
bind[0].buffer = (void*)type.c_str();
bind[0].buffer_length = type.length();
bind[0].is_null = false;
bind[0].is_null = (my_bool *)0;
bind[1].buffer_type = MYSQL_TYPE_STRING;
bind[1].buffer = (void*)target.c_str();
bind[1].buffer_length = target.length();
bind[1].is_null = false;
bind[1].is_null = (my_bool *)0;
status = mysql_stmt_bind_param(statement, bind);
if (status!=0) {
@ -876,12 +909,12 @@ public:
}
bool IgnoreExists(const CString& type, const CString& target) {
if (type.Equals("nick")) {
for (vector<CString>::iterator it=nickIgnoreList.begin(); it<nickIgnoreList.end(); it++) {
for (std::vector<CString>::iterator it=nickIgnoreList.begin(); it<nickIgnoreList.end(); it++) {
if (target.Equals(*it))
return true;
}
} else if (type.Equals("chan")) {
for (vector<CString>::iterator it=chanIgnoreList.begin(); it<chanIgnoreList.end(); it++) {
for (std::vector<CString>::iterator it=chanIgnoreList.begin(); it<chanIgnoreList.end(); it++) {
if (target.Equals(*it))
return true;
}
@ -890,12 +923,12 @@ public:
}
bool IsIgnored(const CString& type, const CString& target) {
if (type.Equals("nick")) {
for (vector<CString>::iterator it=nickIgnoreList.begin(); it<nickIgnoreList.end(); it++) {
for (std::vector<CString>::iterator it=nickIgnoreList.begin(); it<nickIgnoreList.end(); it++) {
if (target.WildCmp(*it))
return true;
}
} else if (type.Equals("chan")) {
for (vector<CString>::iterator it=chanIgnoreList.begin(); it<chanIgnoreList.end(); it++) {
for (std::vector<CString>::iterator it=chanIgnoreList.begin(); it<chanIgnoreList.end(); it++) {
if (target.WildCmp(*it))
return true;
}
@ -979,9 +1012,9 @@ public:
}
}
virtual void OnQuit(const CNick& Nick, const CString& sMessage, const vector<CChan*>& vChans) {
virtual void OnQuit(const CNick& Nick, const CString& sMessage, const std::vector<CChan*>& vChans) {
if (logLevel>=2) {
vector<CChan*>::const_iterator it;
std::vector<CChan*>::const_iterator it;
for (it=vChans.begin(); it!=vChans.end(); it++) {
CChan& channel = **it;
AddMessage(channel.GetName(),Nick.GetNickMask(),"QUIT",sMessage);
@ -997,13 +1030,13 @@ public:
virtual void OnPart(const CNick& Nick, CChan& Channel, const CString& sMessage) {
if (logLevel>=2) {
AddMessage(Channel.GetName(),Nick.GetNickMask(),"JOIN",sMessage);
AddMessage(Channel.GetName(),Nick.GetNickMask(),"PART",sMessage);
}
}
virtual void OnNick(const CNick& OldNick, const CString& sNewNick, const vector<CChan*>& vChans) {
virtual void OnNick(const CNick& OldNick, const CString& sNewNick, const std::vector<CChan*>& vChans) {
if (logLevel>=2) {
vector<CChan*>::const_iterator it;
std::vector<CChan*>::const_iterator it;
for (it=vChans.begin(); it!=vChans.end(); it++) {
CChan& channel = **it;
AddMessage(channel.GetName(),OldNick.GetNickMask(),"NICK",sNewNick);
@ -1082,12 +1115,13 @@ public:
//Client Connection
virtual void OnClientLogin() {
SetSetting("clientConnected",GetUNIXTime());
if (autoReplay)
Replay();
}
virtual void OnClientDisconnect() {
bool track = true;
for (vector<CClient *>::iterator it=doNotTrackClient.begin(); it<doNotTrackClient.end(); it++) {
for (std::vector<CClient *>::iterator it=doNotTrackClient.begin(); it<doNotTrackClient.end(); it++) {
if (*it==m_pClient) {
doNotTrackClient.erase(it);
track = false;
@ -1099,6 +1133,10 @@ public:
}
void Replay() {
Replay(0);
}
void Replay(int replayCount) {
if (!databaseConnected)
return;
PutUser(":*LogMySQL!LogMySQL@znc.in NOTICE "+m_pNetwork->GetIRCNick().GetNickMask()+" :Buffer Playback...");
@ -1107,7 +1145,28 @@ public:
MYSQL_STMT *statement = mysql_stmt_init(database);
int status = 0;
if (!replayAll && !lastOnline.empty()) {
if (replayCount!=0) {
status = mysql_stmt_prepare(statement, "SELECT * FROM (SELECT * FROM `messages` ORDER BY `time` DESC LIMIT ?) ORDER BY `time`", 85);
if (status!=0) {
PutUser(":*LogMySQL!LogMySQL@znc.in NOTICE "+m_pNetwork->GetIRCNick().GetNickMask()+" :Playback failed due to sql problem.");
return;
}
MYSQL_BIND bind[1];
memset(bind, 0, sizeof(bind));
bind[0].buffer_type = MYSQL_TYPE_LONG;
bind[0].buffer = (void*)&replayCount;
bind[0].buffer_length = 0;
bind[0].is_null = (my_bool *)0;
status = mysql_stmt_bind_param(statement, bind);
if (status!=0) {
PutUser(":*LogMySQL!LogMySQL@znc.in NOTICE "+m_pNetwork->GetIRCNick().GetNickMask()+" :Playback failed due to sql problem.");
mysql_stmt_close(statement);
return;
}
} else if (!replayAll && !lastOnline.empty()) {
status = mysql_stmt_prepare(statement, "SELECT * FROM `messages` WHERE `time`>? ORDER BY `time`", 55);
if (status!=0) {
PutUser(":*LogMySQL!LogMySQL@znc.in NOTICE "+m_pNetwork->GetIRCNick().GetNickMask()+" :Playback failed due to sql problem.");
@ -1120,7 +1179,7 @@ public:
bind[0].buffer_type = MYSQL_TYPE_STRING;
bind[0].buffer = (void*)lastOnline.c_str();
bind[0].buffer_length = lastOnline.length();
bind[0].is_null = false;
bind[0].is_null = (my_bool *)0;
status = mysql_stmt_bind_param(statement, bind);
if (status!=0) {
@ -1149,10 +1208,10 @@ public:
MYSQL_FIELD *fields = mysql_fetch_fields(result);
MYSQL_BIND results[columnCount];
memset(results, 0, sizeof(results));
map<unsigned int,char *> columnData;
map<unsigned int,unsigned long> columnLength;
map<unsigned int,bool> columnNull;
map<unsigned int,CString> columns;
std::map<unsigned int,char *> columnData;
std::map<unsigned int,unsigned long> columnLength;
std::map<unsigned int,bool> columnNull;
std::map<unsigned int,CString> columns;
for (unsigned int i=0; i<columnCount; i++) {
columns[i] = CString(fields[i].name);
if (columns[i].empty()) {
@ -1182,7 +1241,7 @@ public:
if (status!=0)
break;
map<CString,CString> data;
std::map<CString,CString> data;
for (unsigned int i=0; i<columnCount; i++) {
if (columnNull[i]) {
data[columns[i]] = "";
@ -1266,13 +1325,14 @@ private:
bool databaseConnected;
bool connected;
bool replayAll;
bool autoReplay;
unsigned long logLimit;
int logLevel;
vector<CString> nickIgnoreList;
vector<CString> chanIgnoreList;
std::vector<CString> nickIgnoreList;
std::vector<CString> chanIgnoreList;
vector<CClient *> doNotTrackClient;
std::vector<CClient *> doNotTrackClient;
};
template<> void TModInfo<CLogMySQL>(CModInfo& Info) {

1189
logsqlite-seen.cpp Executable file

File diff suppressed because it is too large Load Diff

View File

@ -30,8 +30,9 @@ class CLogSQLite : public CModule {
public:
MODCONSTRUCTOR(CLogSQLite) {
AddHelpCommand();
AddCommand("Replay", static_cast<CModCommand::ModCmdFunc>(&CLogSQLite::ReplayCommand), "", "Play back the messages received.");
AddCommand("Replay", static_cast<CModCommand::ModCmdFunc>(&CLogSQLite::ReplayCommand), "[0-9]*", "Play back messages received since last recorded disconnect or to count.");
AddCommand("ReplayAll", static_cast<CModCommand::ModCmdFunc>(&CLogSQLite::ReplayAllCommand), "[1|0]", "Replay all messages stored.");
AddCommand("AutoReplay", static_cast<CModCommand::ModCmdFunc>(&CLogSQLite::AutoReplayCommand), "[1|0]", "Replay on connect.");
AddCommand("LogLimit", static_cast<CModCommand::ModCmdFunc>(&CLogSQLite::LogLimitCommand), "[0-9]+", "Limit the amount of items to store into the log.");
AddCommand("LogLevel", static_cast<CModCommand::ModCmdFunc>(&CLogSQLite::LogLevelCommand), "[0-4]", "Log level.");
@ -43,7 +44,12 @@ public:
}
void ReplayCommand(const CString &sLine) {
CString sArgs = sLine.Token(1, true);
if (!sArgs.empty()) {
Replay(sArgs.ToInt());
} else {
Replay();
}
PutModule("Replayed");
}
@ -61,7 +67,24 @@ public:
CString status = (replayAll ? "On" : "Off");
CString now = (sArgs.empty() || help ? "" : "now ");
PutModule("ReplayAll is "+now+"set to: "+=status);
PutModule("ReplayAll is "+now+"set to: "+status);
}
void AutoReplayCommand(const CString &sLine) {
CString sArgs = sLine.Token(1, true);
bool help = sArgs.Equals("HELP");
if (help) {
PutModule("On: Replay on connect.");
PutModule("Off: Require replay command to replay.");
} else if (!sArgs.empty()) {
autoReplay = sArgs.ToBool();
SetSetting("autoReplay", (autoReplay ? "1" : "0"));
}
CString status = (autoReplay ? "On" : "Off");
CString now = (sArgs.empty() || help ? "" : "now ");
PutModule("AutoReplay is "+now+"set to: "+status);
}
void LogLimitCommand(const CString &sLine) {
@ -182,7 +205,7 @@ public:
} else {
PutModule("Nick ignore list contains:");
for (vector<CString>::iterator it=nickIgnoreList.begin(); it<nickIgnoreList.end(); it++) {
for (std::vector<CString>::iterator it=nickIgnoreList.begin(); it<nickIgnoreList.end(); it++) {
PutModule(*it);
}
}
@ -192,7 +215,7 @@ public:
} else {
PutModule("Channel ignore list contains:");
for (vector<CString>::iterator it=chanIgnoreList.begin(); it<chanIgnoreList.end(); it++) {
for (std::vector<CString>::iterator it=chanIgnoreList.begin(); it<chanIgnoreList.end(); it++) {
PutModule(*it);
}
}
@ -200,7 +223,7 @@ public:
void DoNotTrack(const CString &sLine) {
bool tracking = true;
for (vector<CClient *>::iterator it=doNotTrackClient.begin(); it<doNotTrackClient.end(); it++) {
for (std::vector<CClient *>::iterator it=doNotTrackClient.begin(); it<doNotTrackClient.end(); it++) {
if (*it==m_pClient) {
tracking = false;
break;
@ -237,9 +260,10 @@ public:
sqlite3_finalize(result);
SetSetting("replayAll","0");
SetSetting("autoReplay","1");
SetSetting("logLimit","1");
SetSetting("logLevel","1");
SetSetting("version","2");
SetSetting("version","3");
}
}
}
@ -273,9 +297,6 @@ public:
}
}
}
replayAll = atoi(GetSetting("replayAll").c_str());
logLimit = strtoul(GetSetting("logLimit").c_str(), NULL, 10);
logLevel = atoi(GetSetting("logLevel").c_str());
unsigned long version = strtoul(GetSetting("version").c_str(), NULL, 10);
if (version==0) {
@ -326,6 +347,16 @@ public:
SetSetting("version","2");
version = 2;
}
if (version==2) {
SetSetting("autoReplay","1");
SetSetting("version","3");
version = 3;
}
replayAll = atoi(GetSetting("replayAll").c_str());
autoReplay = atoi(GetSetting("autoReplay").c_str());
logLimit = strtoul(GetSetting("logLimit").c_str(), NULL, 10);
logLevel = atoi(GetSetting("logLevel").c_str());
UpdateIgnoreLists();
@ -404,7 +435,7 @@ public:
int dataCount = sqlite3_data_count(result);
if (dataCount!=1) {
sqlite3_finalize(result);
cout << "LogSQLite: We are only suppose to receive 1 field. We received the count of " << dataCount << " fields.\n";
std::cout << "LogSQLite: We are only suppose to receive 1 field. We received the count of " << dataCount << " fields.\n";
return;
}
unsigned long count = strtoul((const char *)sqlite3_column_text(result, 0), NULL, 10);
@ -433,7 +464,7 @@ public:
dataCount = sqlite3_data_count(result);
if (dataCount!=1) {
sqlite3_finalize(result);
cout << "LogSQLite: We are only suppose to receive 1 field. We received the count of " << dataCount << " fields.\n";
std::cout << "LogSQLite: We are only suppose to receive 1 field. We received the count of " << dataCount << " fields.\n";
break;
}
@ -486,7 +517,6 @@ public:
}
status = sqlite3_bind_text(result, 2, name.c_str(), name.length(), SQLITE_STATIC);
if (status!=SQLITE_OK) {
sqlite3_finalize(result);
return;
}
@ -533,7 +563,7 @@ public:
int dataCount = sqlite3_data_count(result);
if (dataCount!=1) {
sqlite3_finalize(result);
cout << "LogSQLite: Settings are only suppose to return 1 as the field count. We received the count of " << dataCount << " fields.\n";
std::cout << "LogSQLite: Settings are only suppose to return 1 as the field count. We received the count of " << dataCount << " fields.\n";
return stringValue;
}
stringValue = CString((const char *)sqlite3_column_text(result, 0));
@ -640,12 +670,12 @@ public:
}
bool IgnoreExists(const CString& type, const CString& target) {
if (type.Equals("nick")) {
for (vector<CString>::iterator it=nickIgnoreList.begin(); it<nickIgnoreList.end(); it++) {
for (std::vector<CString>::iterator it=nickIgnoreList.begin(); it<nickIgnoreList.end(); it++) {
if (target.Equals(*it))
return true;
}
} else if (type.Equals("chan")) {
for (vector<CString>::iterator it=chanIgnoreList.begin(); it<chanIgnoreList.end(); it++) {
for (std::vector<CString>::iterator it=chanIgnoreList.begin(); it<chanIgnoreList.end(); it++) {
if (target.Equals(*it))
return true;
}
@ -654,12 +684,12 @@ public:
}
bool IsIgnored(const CString& type, const CString& target) {
if (type.Equals("nick")) {
for (vector<CString>::iterator it=nickIgnoreList.begin(); it<nickIgnoreList.end(); it++) {
for (std::vector<CString>::iterator it=nickIgnoreList.begin(); it<nickIgnoreList.end(); it++) {
if (target.WildCmp(*it))
return true;
}
} else if (type.Equals("chan")) {
for (vector<CString>::iterator it=chanIgnoreList.begin(); it<chanIgnoreList.end(); it++) {
for (std::vector<CString>::iterator it=chanIgnoreList.begin(); it<chanIgnoreList.end(); it++) {
if (target.WildCmp(*it))
return true;
}
@ -743,9 +773,9 @@ public:
}
}
virtual void OnQuit(const CNick& Nick, const CString& sMessage, const vector<CChan*>& vChans) {
virtual void OnQuit(const CNick& Nick, const CString& sMessage, const std::vector<CChan*>& vChans) {
if (logLevel>=2) {
vector<CChan*>::const_iterator it;
std::vector<CChan*>::const_iterator it;
for (it=vChans.begin(); it!=vChans.end(); it++) {
CChan& channel = **it;
AddMessage(channel.GetName(),Nick.GetNickMask(),"QUIT",sMessage);
@ -761,13 +791,13 @@ public:
virtual void OnPart(const CNick& Nick, CChan& Channel, const CString& sMessage) {
if (logLevel>=2) {
AddMessage(Channel.GetName(),Nick.GetNickMask(),"JOIN",sMessage);
AddMessage(Channel.GetName(),Nick.GetNickMask(),"PART",sMessage);
}
}
virtual void OnNick(const CNick& OldNick, const CString& sNewNick, const vector<CChan*>& vChans) {
virtual void OnNick(const CNick& OldNick, const CString& sNewNick, const std::vector<CChan*>& vChans) {
if (logLevel>=2) {
vector<CChan*>::const_iterator it;
std::vector<CChan*>::const_iterator it;
for (it=vChans.begin(); it!=vChans.end(); it++) {
CChan& channel = **it;
AddMessage(channel.GetName(),OldNick.GetNickMask(),"NICK",sNewNick);
@ -846,12 +876,13 @@ public:
//Client Connection
virtual void OnClientLogin() {
SetSetting("clientConnected",GetUNIXTime());
if (autoReplay)
Replay();
}
virtual void OnClientDisconnect() {
bool track = true;
for (vector<CClient *>::iterator it=doNotTrackClient.begin(); it<doNotTrackClient.end(); it++) {
for (std::vector<CClient *>::iterator it=doNotTrackClient.begin(); it<doNotTrackClient.end(); it++) {
if (*it==m_pClient) {
doNotTrackClient.erase(it);
track = false;
@ -863,13 +894,29 @@ public:
}
void Replay() {
Replay(0);
}
void Replay(int replayCount) {
PutUser(":*LogSQLite!LogSQLite@znc.in NOTICE "+m_pNetwork->GetIRCNick().GetNickMask()+" :Buffer Playback...");
CString lastOnline = GetSetting("clientDisconnected");
sqlite3_stmt *result;
int status = SQLITE_OK;
if (!replayAll && !lastOnline.empty()) {
if (replayCount!=0) {
status = sqlite3_prepare(database, "SELECT * FROM (SELECT * FROM `messages` ORDER BY `time` DESC LIMIT ?) ORDER BY `time`", -1, &result, NULL);
if (status!=SQLITE_OK) {
PutUser(":*LogSQLite!LogSQLite@znc.in NOTICE "+m_pNetwork->GetIRCNick().GetNickMask()+" :Playback failed due to sql problem.");
return;
}
status = sqlite3_bind_int(result, 1, replayCount);
if (status!=SQLITE_OK) {
PutUser(":*LogSQLite!LogSQLite@znc.in NOTICE "+m_pNetwork->GetIRCNick().GetNickMask()+" :Playback failed due to sql problem.");
sqlite3_finalize(result);
return;
}
} else if (!replayAll && !lastOnline.empty()) {
status = sqlite3_prepare(database, "SELECT * FROM `messages` WHERE `time`>? ORDER BY `time`", -1, &result, NULL);
if (status!=SQLITE_OK) {
PutUser(":*LogSQLite!LogSQLite@znc.in NOTICE "+m_pNetwork->GetIRCNick().GetNickMask()+" :Playback failed due to sql problem.");
@ -890,7 +937,7 @@ public:
}
int columnCount = sqlite3_column_count(result);
map<int,CString> columns;
std::map<int,CString> columns;
for (int i=0; i<columnCount; i++) {
columns[i] = CString(sqlite3_column_name(result, i));
}
@ -904,7 +951,7 @@ public:
if (status!=SQLITE_ROW)
break;
map<CString,CString> data;
std::map<CString,CString> data;
int dataCount = sqlite3_data_count(result);
for (int i=0; i<dataCount; i++) {
data[columns[i]] = CString((const char *)sqlite3_column_text(result, i));
@ -978,13 +1025,14 @@ private:
sqlite3 *database;
bool connected;
bool replayAll;
bool autoReplay;
unsigned long logLimit;
int logLevel;
vector<CString> nickIgnoreList;
vector<CString> chanIgnoreList;
std::vector<CString> nickIgnoreList;
std::vector<CString> chanIgnoreList;
vector<CClient *> doNotTrackClient;
std::vector<CClient *> doNotTrackClient;
};
template<> void TModInfo<CLogSQLite>(CModInfo& Info) {