-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathclientaway.cpp
More file actions
213 lines (168 loc) · 5.75 KB
/
clientaway.cpp
File metadata and controls
213 lines (168 loc) · 5.75 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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
/*
* Copyright (C) 2004-2012 See the AUTHORS file for details.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*/
#include <algorithm>
#include <memory>
#include <znc/Modules.h>
#include <znc/User.h>
#include <znc/IRCNetwork.h>
#include <znc/Chan.h>
#if (VERSION_MAJOR >= 1) && (VERSION_MINOR == 6)
#include <znc/Query.h>
#endif
using std::vector;
#define AWAY_DEFAULT_REASON "Auto away at %time%"
class CClientAwayMod : public CModule {
public:
CString GetAwayReason() const {
CString sAway = GetNV("reason");
if (sAway.empty()) {
sAway = AWAY_DEFAULT_REASON;
}
if (m_pNetwork) {
return m_pNetwork->ExpandString(sAway);
}
return m_pUser->ExpandString(sAway);
}
bool GetAutoAway() const {
return GetNV("autoaway").ToBool();
}
void ListCommand(const CString &sLine) {
CTable Table;
Table.AddColumn("Host");
Table.AddColumn("Network");
Table.AddColumn("Away");
const vector<CClient*> vClients = m_pUser->GetAllClients();
for (vector<CClient*>::const_iterator it = vClients.begin(); it != vClients.end(); ++it) {
CClient *pClient = *it;
Table.AddRow();
Table.SetCell("Host", pClient->GetRemoteIP());
if (pClient->GetNetwork()) {
Table.SetCell("Network", pClient->GetNetwork()->GetName());
}
Table.SetCell("Away", CString(pClient->IsAway()));
}
PutModule(Table);
}
void SetAwayReasonCommand(const CString &sLine) {
CString sReason = sLine.Token(1, true);
if (!sReason.empty()) {
SetNV("reason", sReason);
PutModule("Away reason set to [" + sReason + "]");
}
PutModule("Away message will be expanded to [" + GetAwayReason() + "]");
}
void AutoAwayCommand(const CString &sLine) {
SetNV("autoaway", sLine.Token(1));
if (GetAutoAway()) {
PutModule("Auto away when last client goes away or disconnects enabled.");
} else {
PutModule("Auto away when last client goes away or disconnects disabled.");
}
}
void SetAwayCommand(const CString &sLine) {
const vector<CClient*> vClients = m_pUser->GetAllClients();
CString sHostname = sLine.Token(1);
unsigned int count = 0;
for (vector<CClient*>::const_iterator it = vClients.begin(); it != vClients.end(); ++it) {
CClient *pClient = *it;
if (sHostname.empty() || pClient->GetRemoteIP().Equals(sHostname)) {
pClient->SetAway(true);
++count;
}
}
if (count == 1) {
PutModule(CString(count) + " client has been set away");
} else {
PutModule(CString(count) + " clients have been set away");
}
}
MODCONSTRUCTOR(CClientAwayMod) {
AddHelpCommand();
AddCommand("List", static_cast<CModCommand::ModCmdFunc>(&CClientAwayMod::ListCommand),
"", "List all clients");
AddCommand("Reason", static_cast<CModCommand::ModCmdFunc>(&CClientAwayMod::SetAwayReasonCommand),
"[reason]", "Prints and optionally sets the away reason.");
AddCommand("AutoAway", static_cast<CModCommand::ModCmdFunc>(&CClientAwayMod::AutoAwayCommand),
"yes or no", "Should we auto away you when the last client goes away or disconnects");
AddCommand("SetAway", static_cast<CModCommand::ModCmdFunc>(&CClientAwayMod::SetAwayCommand),
"hostname", "Set any clients matching hostname as away/unaway");
}
virtual void OnClientLogin() {
if (GetAutoAway() && m_pNetwork && m_pNetwork->IsIRCAway()) {
PutIRC("AWAY");
}
}
virtual void OnClientDisconnect() {
if (GetAutoAway() && m_pNetwork && !m_pNetwork->IsIRCAway() && !m_pNetwork->IsUserOnline()) {
PutIRC("AWAY :" + GetAwayReason());
}
}
virtual void OnIRCConnected() {
if (GetAutoAway() && !m_pNetwork->IsUserOnline()) {
PutIRC("AWAY :" + GetAwayReason());
}
}
virtual EModRet OnUserRaw(CString& sLine) {
CString sCmd = sLine.Token(0);
if (sCmd.Equals("AWAY")) {
if (m_pClient->IsAway()) {
m_pClient->SetAway(false);
m_pClient->PutClient(":irc.znc.in 305 " + m_pClient->GetNick() + " :You are no longer marked as being away");
if (m_pNetwork) {
const vector<CChan*>& vChans = m_pNetwork->GetChans();
vector<CChan*>::const_iterator it;
for (it = vChans.begin(); it != vChans.end(); ++it) {
// Skip channels which are detached or we don't use keepbuffer
if (!(*it)->IsDetached() && (*it)->AutoClearChanBuffer()) {
(*it)->ClearBuffer();
}
}
#if (VERSION_MAJOR >= 1) && (VERSION_MINOR == 6)
std::for_each(GetNetwork()->GetQueries().begin(), GetNetwork()->GetQueries().end(), std::default_delete<CQuery>());
#else
m_pNetwork->ClearQueryBuffer();
#endif
if (GetAutoAway() && m_pNetwork->IsIRCAway()) {
PutIRC("AWAY");
}
}
} else {
m_pClient->SetAway(true);
m_pClient->PutClient(":irc.znc.in 306 " + m_pClient->GetNick() + " :You have been marked as being away");
if (GetAutoAway() && m_pNetwork && !m_pNetwork->IsIRCAway() && !m_pNetwork->IsUserOnline()) {
// Use the supplied reason if there was one
CString sAwayReason = sLine.Token(1, true).TrimPrefix_n();
if (sAwayReason.empty()) {
sAwayReason = GetAwayReason();
}
PutIRC("AWAY :" + sAwayReason);
}
}
return HALTCORE;
}
return CONTINUE;
}
virtual EModRet OnRaw(CString& sLine) {
// We do the same as ZNC would without the OnRaw hook,
// except we do not forward 305's or 306's to clients
CString sCmd = sLine.Token(1);
if (sCmd.Equals("305")) {
m_pNetwork->SetIRCAway(false);
return HALTCORE;
} else if (sCmd.Equals("306")) {
m_pNetwork->SetIRCAway(true);
return HALTCORE;
}
return CONTINUE;
}
};
template<> void TModInfo<CClientAwayMod>(CModInfo& Info) {
Info.SetWikiPage("clientaway");
Info.AddType(CModInfo::NetworkModule);
}
USERMODULEDEFS(CClientAwayMod, "This module allows you to set clients away independently, and auto away")