diff options
-rw-r--r-- | docs/RPC/rpc_data.md | 6 | ||||
-rw-r--r-- | include/users.h | 10 | ||||
-rw-r--r-- | modules/protocol/inspircd.cpp | 19 | ||||
-rw-r--r-- | modules/rpc/rpc_data.cpp | 11 | ||||
-rw-r--r-- | src/messages.cpp | 8 | ||||
-rw-r--r-- | src/users.cpp | 18 |
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> ¶ms, 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> ¶ms, 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> ¶ms, 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); |