Skip to content

Commit

Permalink
Add support for the IRCv3 extended-monitor specification.
Browse files Browse the repository at this point in the history
Co-authored-by: Sadie Powell <[email protected]>
  • Loading branch information
delthas and SadieCat authored Nov 2, 2022
1 parent 8c0eb6d commit 6939a79
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 6 deletions.
92 changes: 92 additions & 0 deletions include/modules/monitor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* InspIRCd -- Internet Relay Chat Daemon
*
* Copyright (C) 2022 Sadie Powell <[email protected]>
* Copyright (C) 2021 delthas <[email protected]>
*
* This file is part of InspIRCd. InspIRCd is free software: you can
* redistribute it and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation, version 2.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/


#pragma once

namespace Monitor
{
class APIBase;
class API;
class ForEachHandler;
class WriteWatchersWithCap;
}

class Monitor::APIBase
: public DataProvider
{
public:
APIBase(Module* parent)
: DataProvider(parent, "monitor")
{
}

/** Runs the provided handler for all watchers of a user
* @param user The user to check watchers for.
* @param handler The handler to execute for each watcher of that event.
* @param extended_only Whether to only run the handler for watchers using the extended-notify cap.
*/
virtual void ForEachWatcher(User* user, ForEachHandler& handler, bool extended_only = true) = 0;
};

class Monitor::API CXX11_FINAL
: public dynamic_reference<Monitor::APIBase>
{
public:
API(Module* parent)
: dynamic_reference<Monitor::APIBase>(parent, "monitor")
{
}
};

class Monitor::ForEachHandler
{
public:
/** Method to execute for each watcher of a user.
* Derived classes must implement this.
* @param user Current watcher of the user
*/
virtual void Execute(LocalUser* user) = 0;
};


class Monitor::WriteWatchersWithCap
: public Monitor::ForEachHandler
{
private:
const Cap::Capability& cap;
ClientProtocol::Event& ev;
already_sent_t sentid;

void Execute(LocalUser* user) CXX11_OVERRIDE
{
if (user->already_sent != sentid && cap.get(user))
user->Send(ev);
}

public:
WriteWatchersWithCap(Monitor::API& monitorapi, User* user, ClientProtocol::Event& event, const Cap::Capability& capability, already_sent_t id)
: cap(capability)
, ev(event)
, sentid(id)
{
if (monitorapi)
monitorapi->ForEachWatcher(user, *this);
}
};
9 changes: 7 additions & 2 deletions src/modules/m_ircv3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "modules/away.h"
#include "modules/cap.h"
#include "modules/ircv3.h"
#include "modules/monitor.h"

class AwayMessage : public ClientProtocol::Message
{
Expand Down Expand Up @@ -120,6 +121,7 @@ class ModuleIRCv3
JoinHook joinhook;

ClientProtocol::EventProvider accountprotoev;
Monitor::API monitorapi;

public:
ModuleIRCv3()
Expand All @@ -128,6 +130,7 @@ class ModuleIRCv3
, cap_accountnotify(this, "account-notify")
, joinhook(this)
, accountprotoev(this, "ACCOUNT")
, monitorapi(this)
{
}

Expand All @@ -150,7 +153,8 @@ class ModuleIRCv3
const std::string& param = (newaccount.empty() ? joinhook.asterisk : newaccount);
msg.PushParamRef(param);
ClientProtocol::Event accountevent(accountprotoev, msg);
IRCv3::WriteNeighborsWithCap(user, accountevent, cap_accountnotify, true);
IRCv3::WriteNeighborsWithCap res(user, accountevent, cap_accountnotify, true);
Monitor::WriteWatchersWithCap(monitorapi, user, accountevent, cap_accountnotify, res.GetAlreadySentId());
}

void OnUserAway(User* user) CXX11_OVERRIDE
Expand All @@ -161,7 +165,8 @@ class ModuleIRCv3
// Going away: n!u@h AWAY :reason
AwayMessage msg(user);
ClientProtocol::Event awayevent(joinhook.awayprotoev, msg);
IRCv3::WriteNeighborsWithCap(user, awayevent, joinhook.awaycap);
IRCv3::WriteNeighborsWithCap res(user, awayevent, joinhook.awaycap);
Monitor::WriteWatchersWithCap(monitorapi, user, awayevent, joinhook.awaycap, res.GetAlreadySentId());
}

void OnUserBack(User* user) CXX11_OVERRIDE
Expand Down
6 changes: 5 additions & 1 deletion src/modules/m_ircv3_chghost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@
#include "inspircd.h"
#include "modules/cap.h"
#include "modules/ircv3.h"
#include "modules/monitor.h"

class ModuleIRCv3ChgHost : public Module
{
Cap::Capability cap;
ClientProtocol::EventProvider protoevprov;
Monitor::API monitorapi;

void DoChgHost(User* user, const std::string& ident, const std::string& host)
{
Expand All @@ -36,13 +38,15 @@ class ModuleIRCv3ChgHost : public Module
msg.PushParamRef(ident);
msg.PushParamRef(host);
ClientProtocol::Event protoev(protoevprov, msg);
IRCv3::WriteNeighborsWithCap(user, protoev, cap, true);
IRCv3::WriteNeighborsWithCap res(user, protoev, cap, true);
Monitor::WriteWatchersWithCap(monitorapi, user, protoev, cap, res.GetAlreadySentId());
}

public:
ModuleIRCv3ChgHost()
: cap(this, "chghost")
, protoevprov(this, "CHGHOST")
, monitorapi(this)
{
}

Expand Down
25 changes: 23 additions & 2 deletions src/modules/m_monitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@


#include "inspircd.h"
#include "modules/cap.h"
#include "modules/monitor.h"

namespace IRCv3
{
Expand Down Expand Up @@ -369,10 +371,13 @@ class CommandMonitor : public SplitCommand
}
};

class ModuleMonitor : public Module
class ModuleMonitor
: public Module
, public Monitor::APIBase
{
IRCv3::Monitor::Manager manager;
CommandMonitor cmd;
Cap::Capability extendedcap;

void SendAlert(unsigned int numeric, const std::string& nick)
{
Expand All @@ -389,8 +394,10 @@ class ModuleMonitor : public Module

public:
ModuleMonitor()
: manager(this, "monitor")
: Monitor::APIBase(this)
, manager(this, "monitor")
, cmd(this, manager)
, extendedcap(this, "draft/extended-monitor")
{
}

Expand Down Expand Up @@ -428,6 +435,20 @@ class ModuleMonitor : public Module
tokens["MONITOR"] = ConvToStr(cmd.maxmonitor);
}

void ForEachWatcher(User* user, Monitor::ForEachHandler& handler, bool extended_only) CXX11_OVERRIDE
{
const IRCv3::Monitor::WatcherList* list = manager.GetWatcherList(user->nick);
if (!list)
return;

for (IRCv3::Monitor::WatcherList::const_iterator i = list->begin(); i != list->end(); ++i)
{
LocalUser* curr = *i;
if(!extended_only || extendedcap.get(curr))
handler.Execute(curr);
}
}

Version GetVersion() CXX11_OVERRIDE
{
return Version("Adds the /MONITOR command which allows users to find out when their friends are connected to the server.", VF_VENDOR);
Expand Down
6 changes: 5 additions & 1 deletion src/modules/m_setname.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "inspircd.h"
#include "modules/ircv3.h"
#include "modules/ircv3_replies.h"
#include "modules/monitor.h"

class CommandSetName : public SplitCommand
{
Expand Down Expand Up @@ -71,11 +72,13 @@ class ModuleSetName : public Module
private:
CommandSetName cmd;
ClientProtocol::EventProvider setnameevprov;
Monitor::API monitorapi;

public:
ModuleSetName()
: cmd(this)
, setnameevprov(this, "SETNAME")
, monitorapi(this)
{
}

Expand All @@ -99,7 +102,8 @@ class ModuleSetName : public Module
ClientProtocol::Message msg("SETNAME", user);
msg.PushParamRef(real);
ClientProtocol::Event protoev(setnameevprov, msg);
IRCv3::WriteNeighborsWithCap(user, protoev, cmd.cap, true);
IRCv3::WriteNeighborsWithCap res(user, protoev, cmd.cap, true);
Monitor::WriteWatchersWithCap(monitorapi, user, protoev, cmd.cap, res.GetAlreadySentId());
}

Version GetVersion() CXX11_OVERRIDE
Expand Down

0 comments on commit 6939a79

Please sign in to comment.