-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathm_historymod.cpp
More file actions
130 lines (114 loc) · 4.05 KB
/
m_historymod.cpp
File metadata and controls
130 lines (114 loc) · 4.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <json/json.h>
#include "inspircd.h"
/* $ModDesc: App filtered auto-enabled channel history */
/* $CompileFlags: -L../../lib -I../../include/ -std=c++0x */
/* $LinkerFlags: -L../../lib -ljson */
// log - convenient synchronized logging function.
Mutex* loggingMutex = new Mutex();
void log(std::string s){
loggingMutex->Lock();
ServerInstance->Logs->Log("m_historymod", DEFAULT, s);
loggingMutex->Unlock();
}
struct HistoryItem{
time_t ts;
std::string line;
HistoryItem(const std::string& Line) : ts(ServerInstance->Time()), line(Line) {}
};
struct HistoryList{
std::deque<HistoryItem> lines;
unsigned int maxlen, maxtime;
HistoryList(unsigned int len, unsigned int time) : maxlen(len), maxtime(time) {}
};
// See m_chanhistory.cpp
// TODO: When do we clear history?
// I think we'd do this but I don't see history chan doing it?
// i think it assumes the mode gets unset before the channel dies? or does
// ext notice when its map-key dies? In any case, when do we call delete?
// ext.unset(channel);
class HistoryMod : public Module{
SimpleExtItem<HistoryList> ext;
unsigned int maxlines;
unsigned int maxtime;
public:
HistoryMod() : ext("historymod", this), maxlines(100) {}
void init(){
maxtime = ServerInstance->Duration("86400");
// ext is like a map. We map channel to historylist.
ServerInstance->Modules->AddService(ext);
Implementation eventlist[] = {
I_OnPostJoin,
I_OnUserMessage
};
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
virtual ~HistoryMod(){
}
void OnUserMessage(User* user,
void* dest,
int target_type,
const std::string &text,
char status,
const CUList&){
if (target_type==TYPE_CHANNEL && status==0){
Json::Value root;
Json::Reader reader;
bool parsingSuccessful = reader.parse(text, root);
if(!parsingSuccessful){
log("historymod: Could not parse JSON from message, ignoring.");
log(reader.getFormattedErrorMessages());
return;
}
std::string content = root.get("m", "NONE" ).asString();
if(content!="NONE"){
Json::Value rootInner;
Json::Reader readerInner;
parsingSuccessful = readerInner.parse(content, rootInner);
if(!parsingSuccessful){
log("historymod: Could not parse JSON from message, ignoring.");
log(readerInner.getFormattedErrorMessages());
return;
}
std::string messageType = rootInner.get("t", "NONE" ).asString();
if(messageType=="m"){
Channel* c = (Channel*)dest;
HistoryList* list = ext.get(c);
if(list){
char buf[MAXBUF];
snprintf(buf, MAXBUF, ":%s PRIVMSG %s :%s",
user->GetFullHost().c_str(), c->name.c_str(), text.c_str());
list->lines.push_back(HistoryItem(buf));
if (list->lines.size() > list->maxlen){
list->lines.pop_front();
}
}else{
log("historymod: No history for channel");
}
}
}
}
}
void OnPostJoin(Membership* memb){
if(IS_REMOTE(memb->user))
return;
Channel* channel = memb->chan;
HistoryList* list = ext.get(channel);
if(!list){
list = new HistoryList(maxlines, maxtime);
ext.set(channel, list);
}
time_t mintime = ServerInstance->Time() - list->maxtime;
for(std::deque<HistoryItem>::iterator i = list->lines.begin();
i!=list->lines.end();
++i)
{
if (i->ts >= mintime){
memb->user->Write(i->line);
}
}
}
Version GetVersion(){
return Version("App filtered channel history replayed on join");
}
};
MODULE_INIT(HistoryMod)