mirror of
https://github.com/znc/znc.git
synced 2026-07-13 21:31:27 +02:00
WebMod-enabled the lastseen module. Especially useful for setups with many users,
makes finding inactive accounts easy. git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@1880 726aef4b-f618-498e-8847-2d620e286838
This commit is contained in:
+75
-20
@@ -7,30 +7,34 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "User.h"
|
#include "User.h"
|
||||||
|
#include "Chan.h"
|
||||||
#include "znc.h"
|
#include "znc.h"
|
||||||
|
|
||||||
using std::map;
|
using std::map;
|
||||||
|
using std::pair;
|
||||||
|
using std::multimap;
|
||||||
|
|
||||||
class CLastSeenMod : public CGlobalModule {
|
class CLastSeenMod : public CGlobalModule {
|
||||||
|
private:
|
||||||
|
time_t GetTime(const CUser *pUser) {
|
||||||
|
return GetNV(pUser->GetUserName()).ToULong();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetTime(const CUser *pUser) {
|
||||||
|
SetNV(pUser->GetUserName(), CString(time(NULL)));
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef multimap<time_t, CUser*> MTimeMulti;
|
||||||
|
typedef map<CString, CUser*> MUsers;
|
||||||
public:
|
public:
|
||||||
GLOBALMODCONSTRUCTOR(CLastSeenMod)
|
GLOBALMODCONSTRUCTOR(CLastSeenMod) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~CLastSeenMod() {}
|
virtual ~CLastSeenMod() {}
|
||||||
|
|
||||||
time_t GetTime(CUser *pUser)
|
// IRC stuff:
|
||||||
{
|
|
||||||
return GetNV(pUser->GetUserName()).ToULong();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetTime(CUser *pUser)
|
virtual void OnModCommand(const CString& sLine) {
|
||||||
{
|
|
||||||
SetNV(pUser->GetUserName(), CString(time(NULL)));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void OnModCommand(const CString& sLine)
|
|
||||||
{
|
|
||||||
const CString sCommand = sLine.Token(0).AsLower();
|
const CString sCommand = sLine.Token(0).AsLower();
|
||||||
|
|
||||||
if (!GetUser()->IsAdmin()) {
|
if (!GetUser()->IsAdmin()) {
|
||||||
@@ -40,8 +44,8 @@ public:
|
|||||||
|
|
||||||
if (sCommand == "show") {
|
if (sCommand == "show") {
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
const map<CString, CUser*>& mUsers = CZNC::Get().GetUserMap();
|
const MUsers& mUsers = CZNC::Get().GetUserMap();
|
||||||
map<CString, CUser*>::const_iterator it;
|
MUsers::const_iterator it;
|
||||||
CTable Table;
|
CTable Table;
|
||||||
|
|
||||||
Table.AddColumn("User");
|
Table.AddColumn("User");
|
||||||
@@ -68,17 +72,68 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void OnClientLogin()
|
// Event stuff:
|
||||||
{
|
|
||||||
|
virtual void OnClientLogin() {
|
||||||
SetTime(GetUser());
|
SetTime(GetUser());
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void OnClientDisconnect()
|
virtual void OnClientDisconnect() {
|
||||||
{
|
|
||||||
SetTime(GetUser());
|
SetTime(GetUser());
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
virtual EModRet OnDeleteUser(CUser& User) {
|
||||||
|
DelNV(User.GetUserName());
|
||||||
|
return CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Web stuff:
|
||||||
|
|
||||||
|
virtual bool WebRequiresLogin() { return true; }
|
||||||
|
virtual bool WebRequiresAdmin() { return false; }
|
||||||
|
virtual CString GetWebMenuTitle() { return "Last Seen"; }
|
||||||
|
|
||||||
|
virtual bool OnWebRequest(CWebSock& WebSock, const CString& sPageName, CTemplate& Tmpl) {
|
||||||
|
if (sPageName.empty() || sPageName == "index") {
|
||||||
|
MTimeMulti mmSorted;
|
||||||
|
const MUsers& mUsers = CZNC::Get().GetUserMap();
|
||||||
|
|
||||||
|
for (MUsers::const_iterator uit = mUsers.begin(); uit != mUsers.end(); ++uit) {
|
||||||
|
mmSorted.insert(pair<time_t, CUser*>(GetTime(uit->second), uit->second));
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[1024] = {0};
|
||||||
|
|
||||||
|
for (MTimeMulti::const_iterator it = mmSorted.begin(); it != mmSorted.end(); ++it) {
|
||||||
|
CUser *pUser = it->second;
|
||||||
|
CTemplate& Row = Tmpl.AddRow("UserLoop");
|
||||||
|
|
||||||
|
Row["Username"] = pUser->GetUserName();
|
||||||
|
Row["IsSelf"] = CString(pUser == WebSock.GetSession()->GetUser());
|
||||||
|
|
||||||
|
if(it->first > 0) {
|
||||||
|
strftime(buf, sizeof(buf), "%c", localtime(&it->first));
|
||||||
|
Row["LastSeen"] = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
Row["Info"] = CString(pUser->GetClients().size()) + " client(s)";
|
||||||
|
if(!pUser->GetCurrentServer()) {
|
||||||
|
Row["Info"] += ", not connected to IRC";
|
||||||
|
} else {
|
||||||
|
unsigned int uChans = 0;
|
||||||
|
const vector<CChan*>& vChans = pUser->GetChans();
|
||||||
|
for (unsigned int a = 0; a < vChans.size(); a++) {
|
||||||
|
if (vChans[a]->IsOn()) uChans++;
|
||||||
|
}
|
||||||
|
Row["Info"] += ", joined to " + CString(uChans) + " channel(s)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
GLOBALMODULEDEFS(CLastSeenMod, "Collects data about when a user last logged in")
|
GLOBALMODULEDEFS(CLastSeenMod, "Collects data about when a user last logged in")
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<? INC Header.tmpl ?>
|
||||||
|
|
||||||
|
<table class="data">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td>User</td>
|
||||||
|
<td>Last Seen</td>
|
||||||
|
<td>Info</td>
|
||||||
|
<td>Action</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<? LOOP UserLoop ?>
|
||||||
|
<tr class="<? IF __EVEN__ ?>evenrow<? ELSE ?>oddrow<? ENDIF ?>">
|
||||||
|
<td><? VAR Username ?></td>
|
||||||
|
<td><? VAR LastSeen DEFAULT="- unknown -" ?></td>
|
||||||
|
<td><? VAR Info ?></td>
|
||||||
|
<td><span class="nowrap">
|
||||||
|
[<a href="/mods/webadmin/edituser?user=<?VAR Username ESC=URL?>">Edit</a>]
|
||||||
|
<? IF !IsSelf ?>[<a href="/mods/webadmin/deluser?user=<?VAR Username ESC=URL?>" onclick="return confirm('Do you really wish to remove this user?');">Delete</a>]<? ENDIF ?>
|
||||||
|
</span></td>
|
||||||
|
</tr>
|
||||||
|
<? ENDLOOP ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<? ENDIF ?>
|
||||||
|
|
||||||
|
<? INC Footer.tmpl ?>
|
||||||
Reference in New Issue
Block a user