%PDF- %PDF-
Direktori : /data/old/usr/local/include/znc/ |
Current File : //data/old/usr/local/include/znc/Message.h |
/* * Copyright (C) 2004-2018 ZNC, see the NOTICE file for details. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ZNC_MESSAGE_H #define ZNC_MESSAGE_H // Remove this after Feb 2016 when Debian 7 is EOL #if __cpp_ref_qualifiers >= 200710 #define ZNC_LVREFQUAL & #elif defined(__clang__) #define ZNC_LVREFQUAL & #elif __GNUC__ > 4 || \ __GNUC__ == 4 && (__GNUC_MINOR__ > 8 || \ __GNUC_MINOR__ == 8 && __GNUC_PATCHLEVEL__ >= 1) #define ZNC_LVREFQUAL & #else #define ZNC_LVREFQUAL #endif #ifdef SWIG #define ZNC_MSG_DEPRECATED(msg) #else #define ZNC_MSG_DEPRECATED(msg) __attribute__((deprecated(msg))) #endif #include <znc/zncconfig.h> #include <znc/ZNCString.h> #include <znc/Nick.h> #include <sys/time.h> class CChan; class CClient; class CIRCNetwork; /** * Here is a small explanation of how messages on IRC work, and how you can use * this class to get useful information from the parsed message. The output * varies greatly and this advice may not apply to every message type, but this * will hopefully help you understand how it works more accurately. * * @t=some-tag :server.network.net 366 something #channel :End of /NAMES list. * tags nick cmd 0 1 2 * * - `tags` is the IRCv3 tags associated with the message, obtained with * GetTag("t"). the @time tag can also be obtained with GetTime(), some * messages have other tags with them. Tags may not always be present. Refer * to IRCv3 for documentation on tags. * - `nick` is the sender, which can be obtained with GetNick() * - `cmd` is command, which is obtained via GetCommand() * - `0`, `1`, ... are parameters, available via GetParam(n), which removes the * leading colon (:). If you don't want to remove the colon, use * GetParamsColon(). * * For certain events, like a PRIVMSG, convienience commands like GetChan() and * GetNick() are available, this is not true for all CMessage extensions. */ class CMessage { public: explicit CMessage(const CString& sMessage = ""); CMessage(const CNick& Nick, const CString& sCommand, const VCString& vsParams = VCString(), const MCString& mssTags = MCString::EmptyMap); enum class Type { Unknown, Account, Action, Away, Capability, CTCP, Error, Invite, Join, Kick, Mode, Nick, Notice, Numeric, Part, Ping, Pong, Quit, Text, Topic, Wallops, }; Type GetType() const { return m_eType; } bool Equals(const CMessage& Other) const; void Clone(const CMessage& Other); // ZNC <-> IRC CIRCNetwork* GetNetwork() const { return m_pNetwork; } void SetNetwork(CIRCNetwork* pNetwork) { m_pNetwork = pNetwork; } // ZNC <-> CLI CClient* GetClient() const { return m_pClient; } void SetClient(CClient* pClient) { m_pClient = pClient; } CChan* GetChan() const { return m_pChan; } void SetChan(CChan* pChan) { m_pChan = pChan; } CNick& GetNick() { return m_Nick; } const CNick& GetNick() const { return m_Nick; } void SetNick(const CNick& Nick) { m_Nick = Nick; } const CString& GetCommand() const { return m_sCommand; } void SetCommand(const CString& sCommand); const VCString& GetParams() const { return m_vsParams; } void SetParams(const VCString& vsParams); /// @deprecated use GetParamsColon() instead. CString GetParams(unsigned int uIdx, unsigned int uLen = -1) const ZNC_MSG_DEPRECATED("Use GetParamsColon() instead") { return GetParamsColon(uIdx, uLen); } CString GetParamsColon(unsigned int uIdx, unsigned int uLen = -1) const; CString GetParam(unsigned int uIdx) const; void SetParam(unsigned int uIdx, const CString& sParam); const timeval& GetTime() const { return m_time; } void SetTime(const timeval& ts) { m_time = ts; } const MCString& GetTags() const { return m_mssTags; } void SetTags(const MCString& mssTags) { m_mssTags = mssTags; } CString GetTag(const CString& sKey) const; void SetTag(const CString& sKey, const CString& sValue); enum FormatFlags { IncludeAll = 0x0, ExcludePrefix = 0x1, ExcludeTags = 0x2 }; CString ToString(unsigned int uFlags = IncludeAll) const; void Parse(CString sMessage); // Implicit and explicit conversion to a subclass reference. #ifndef SWIG template <typename M> M& As() ZNC_LVREFQUAL { static_assert(std::is_base_of<CMessage, M>{}, "Must be subclass of CMessage"); static_assert(sizeof(M) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); return static_cast<M&>(*this); } template <typename M> const M& As() const ZNC_LVREFQUAL { static_assert(std::is_base_of<CMessage, M>{}, "Must be subclass of CMessage"); static_assert(sizeof(M) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); return static_cast<const M&>(*this); } template <typename M, typename = typename std::enable_if< std::is_base_of<CMessage, M>{}>::type> operator M&() ZNC_LVREFQUAL { return As<M>(); } template <typename M, typename = typename std::enable_if< std::is_base_of<CMessage, M>{}>::type> operator const M&() const ZNC_LVREFQUAL { return As<M>(); } // REGISTER_ZNC_MESSAGE allows SWIG to instantiate correct .As<> calls. #define REGISTER_ZNC_MESSAGE(M) #else // SWIG (as of 3.0.7) doesn't parse ref-qualifiers, and doesn't // differentiate constness. template <typename M> M& As(); #endif private: void InitTime(); void InitType(); CNick m_Nick; CString m_sCommand; VCString m_vsParams; MCString m_mssTags; timeval m_time; CIRCNetwork* m_pNetwork = nullptr; CClient* m_pClient = nullptr; CChan* m_pChan = nullptr; Type m_eType = Type::Unknown; bool m_bColon = false; }; // For gtest #ifdef GTEST_FAIL template <typename M, typename = typename std::enable_if< std::is_base_of<CMessage, M>{}>::type> inline ::std::ostream& operator<<(::std::ostream& os, const M& msg) { return os << msg.ToString().Escape_n(CString::EDEBUG); } #endif // The various CMessage subclasses are "mutable views" to the data held by // CMessage. // They provide convenient access to message type speficic attributes, but are // not // allowed to hold extra data of their own. class CTargetMessage : public CMessage { public: CString GetTarget() const { return GetParam(0); } void SetTarget(const CString& sTarget) { SetParam(0, sTarget); } }; REGISTER_ZNC_MESSAGE(CTargetMessage); class CActionMessage : public CTargetMessage { public: CString GetText() const { return GetParam(1).TrimPrefix_n("\001ACTION ").TrimSuffix_n("\001"); } void SetText(const CString& sText) { SetParam(1, "\001ACTION " + sText + "\001"); } }; REGISTER_ZNC_MESSAGE(CActionMessage); class CCTCPMessage : public CTargetMessage { public: bool IsReply() const { return GetCommand().Equals("NOTICE"); } CString GetText() const { return GetParam(1).TrimPrefix_n("\001").TrimSuffix_n("\001"); } void SetText(const CString& sText) { SetParam(1, "\001" + sText + "\001"); } }; REGISTER_ZNC_MESSAGE(CCTCPMessage); class CJoinMessage : public CTargetMessage { public: CString GetKey() const { return GetParam(1); } void SetKey(const CString& sKey) { SetParam(1, sKey); } }; REGISTER_ZNC_MESSAGE(CJoinMessage); class CModeMessage : public CTargetMessage { public: CString GetModes() const { return GetParamsColon(1).TrimPrefix_n(":"); } }; REGISTER_ZNC_MESSAGE(CModeMessage); class CNickMessage : public CMessage { public: CString GetOldNick() const { return GetNick().GetNick(); } CString GetNewNick() const { return GetParam(0); } void SetNewNick(const CString& sNick) { SetParam(0, sNick); } }; REGISTER_ZNC_MESSAGE(CNickMessage); class CNoticeMessage : public CTargetMessage { public: CString GetText() const { return GetParam(1); } void SetText(const CString& sText) { SetParam(1, sText); } }; REGISTER_ZNC_MESSAGE(CNoticeMessage); class CNumericMessage : public CMessage { public: unsigned int GetCode() const { return GetCommand().ToUInt(); } }; REGISTER_ZNC_MESSAGE(CNumericMessage); class CKickMessage : public CTargetMessage { public: CString GetKickedNick() const { return GetParam(1); } void SetKickedNick(const CString& sNick) { SetParam(1, sNick); } CString GetReason() const { return GetParam(2); } void SetReason(const CString& sReason) { SetParam(2, sReason); } CString GetText() const { return GetReason(); } void SetText(const CString& sText) { SetReason(sText); } }; REGISTER_ZNC_MESSAGE(CKickMessage); class CPartMessage : public CTargetMessage { public: CString GetReason() const { return GetParam(1); } void SetReason(const CString& sReason) { SetParam(1, sReason); } CString GetText() const { return GetReason(); } void SetText(const CString& sText) { SetReason(sText); } }; REGISTER_ZNC_MESSAGE(CPartMessage); class CQuitMessage : public CMessage { public: CString GetReason() const { return GetParam(0); } void SetReason(const CString& sReason) { SetParam(0, sReason); } CString GetText() const { return GetReason(); } void SetText(const CString& sText) { SetReason(sText); } }; REGISTER_ZNC_MESSAGE(CQuitMessage); class CTextMessage : public CTargetMessage { public: CString GetText() const { return GetParam(1); } void SetText(const CString& sText) { SetParam(1, sText); } }; REGISTER_ZNC_MESSAGE(CTextMessage); class CTopicMessage : public CTargetMessage { public: CString GetTopic() const { return GetParam(1); } void SetTopic(const CString& sTopic) { SetParam(1, sTopic); } CString GetText() const { return GetTopic(); } void SetText(const CString& sText) { SetTopic(sText); } }; REGISTER_ZNC_MESSAGE(CTopicMessage); #endif // !ZNC_MESSAGE_H