summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/RPC/rpc_data.md6
-rw-r--r--include/users.h10
-rw-r--r--modules/protocol/inspircd.cpp19
-rw-r--r--modules/rpc/rpc_data.cpp11
-rw-r--r--src/messages.cpp8
-rw-r--r--src/users.cpp18
6 files changed, 57 insertions, 15 deletions
diff --git a/docs/RPC/rpc_data.md b/docs/RPC/rpc_data.md
index aa31fdd6d..a42f7b5be 100644
--- a/docs/RPC/rpc_data.md
+++ b/docs/RPC/rpc_data.md
@@ -414,6 +414,9 @@ account.display | string | The display nickname of the account.
account.opertype | string or null | The account's oper type or null if the account is not a services operator.
account.uniqueid | uint | The unique immutable identifier of the account.
address | string | The IP address the user is connecting from.
+away | map or null | The user's away state or null if they are not away.
+away.message | string | The away message specified by the user.
+away.time | int | The UNIX time at which the user went away.
channels | array[string] | The channels that the user is in prefixed by their status mode prefixes.
chost | string or null | The cloaked hostname of the user or null if they have no cloak.
fingerprint | string or null | The fingerprint of the user's client certificate or null if they are not using one.
@@ -439,7 +442,8 @@ vident | string or null | The virtual ident (username) of the user or
"opertype": "Services Root",
"uniqueid": "17183514657819486040"
},
- "address": "127.0.0.1",
+ "address": "127.0.0.1",
+ "away": null,
"channels": ["@#chan1", "#chan2"],
"chost": "localhost",
"fingerprint": null,
diff --git a/include/users.h b/include/users.h
index 08fa339b2..168b8e4f4 100644
--- a/include/users.h
+++ b/include/users.h
@@ -79,6 +79,10 @@ public: // XXX: exposing a tiny bit too much
time_t timestamp;
/* Is the user as super admin? */
bool super_admin;
+ /* The away message of the user */
+ Anope::string awaymsg;
+ /* The time the user went away */
+ time_t awaytime = 0;
/* Channels the user is in */
typedef std::map<Channel *, ChanUserContainer *> ChanUserList;
@@ -252,6 +256,12 @@ public:
/** Update the last usermask stored for a user. */
void UpdateHost();
+ /** Update the away state for a user. */
+ void SetAway(const Anope::string &msg = "", time_t ts = 0);
+
+ /** Determines whether this user is away. */
+ auto IsAway() const { return awaymsg.empty(); }
+
/** Check if the user has a mode
* @param name Mode name
* @return true or false
diff --git a/modules/protocol/inspircd.cpp b/modules/protocol/inspircd.cpp
index 9535778ae..8ea6b7f7a 100644
--- a/modules/protocol/inspircd.cpp
+++ b/modules/protocol/inspircd.cpp
@@ -1056,17 +1056,22 @@ public:
};
struct IRCDMessageAway final
- : Message::Away
+ : IRCDMessage
{
- IRCDMessageAway(Module *creator) : Message::Away(creator, "AWAY") { SetFlag(FLAG_REQUIRE_USER); }
+ IRCDMessageAway(Module *creator)
+ : IRCDMessage(creator, "AWAY")
+ {
+ SetFlag(FLAG_REQUIRE_USER);
+ SetFlag(FLAG_SOFT_LIMIT);
+ }
void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
- std::vector<Anope::string> newparams(params);
- if (newparams.size() > 1)
- newparams.erase(newparams.begin());
-
- Message::Away::Run(source, newparams, tags);
+ auto *u = source.GetUser();
+ if (params.size() == 2)
+ u->SetAway(params[1], IRCD->ExtractTimestamp(params[0]));
+ else
+ u->SetAway();
}
};
diff --git a/modules/rpc/rpc_data.cpp b/modules/rpc/rpc_data.cpp
index 1e8f990b0..c4ab43d69 100644
--- a/modules/rpc/rpc_data.cpp
+++ b/modules/rpc/rpc_data.cpp
@@ -508,6 +508,17 @@ public:
root.Reply("account", nullptr);
}
+ if (u->IsAway())
+ {
+ root.ReplyMap("away")
+ .Reply("message", u->awaymsg)
+ .Reply("time", u->awaytime);
+ }
+ else
+ {
+ root.Reply("away", nullptr);
+ }
+
auto &channels = root.ReplyArray("channels");
for (const auto &[_, cc] : u->chans)
channels.Reply(cc->status.BuildModePrefixList() + cc->chan->name);
diff --git a/src/messages.cpp b/src/messages.cpp
index 312b867a3..21850134c 100644
--- a/src/messages.cpp
+++ b/src/messages.cpp
@@ -25,13 +25,7 @@ using namespace Message;
void Away::Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags)
{
- const Anope::string &msg = !params.empty() ? params[0] : "";
-
- FOREACH_MOD(OnUserAway, (source.GetUser(), msg));
- if (!msg.empty())
- Log(source.GetUser(), "away") << "is now away: " << msg;
- else
- Log(source.GetUser(), "away") << "is no longer away";
+ source.GetUser()->SetAway(params.empty() ? "" : params[0]);
}
void Capab::Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags)
diff --git a/src/users.cpp b/src/users.cpp
index 63a524488..5887bba2f 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -543,6 +543,24 @@ void User::UpdateHost()
}
}
+void User::SetAway(const Anope::string &msg, time_t ts)
+{
+ FOREACH_MOD(OnUserAway, (this, msg));
+ if (msg.empty())
+ {
+ this->awaymsg.clear();
+ this->awaytime = 0;
+ Log(this, "away") << "is no longer away";
+ }
+ else
+ {
+ this->awaymsg = msg;
+ this->awaytime = ts ? ts : Anope::CurTime;
+ Log(this, "away") << "is now away: " << msg;
+ }
+}
+
+
bool User::HasMode(const Anope::string &mname) const
{
return this->modes.count(mname);