]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_delaymsg.cpp
cf26df8c153516fb97d27bd1f008496ee9f6c675
[user/henk/code/inspircd.git] / src / modules / m_delaymsg.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
5  *
6  * This file is part of InspIRCd.  InspIRCd is free software: you can
7  * redistribute it and/or modify it under the terms of the GNU General Public
8  * License as published by the Free Software Foundation, version 2.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
13  * details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19
20 #include "inspircd.h"
21 #include "modules/ctctags.h"
22
23 class DelayMsgMode : public ParamMode<DelayMsgMode, LocalIntExt>
24 {
25  public:
26         LocalIntExt jointime;
27         DelayMsgMode(Module* Parent)
28                 : ParamMode<DelayMsgMode, LocalIntExt>(Parent, "delaymsg", 'd')
29                 , jointime("delaymsg", ExtensionItem::EXT_MEMBERSHIP, Parent)
30         {
31                 ranktoset = ranktounset = OP_VALUE;
32                 syntax = "<seconds>";
33         }
34
35         bool ResolveModeConflict(std::string& their_param, const std::string& our_param, Channel*) CXX11_OVERRIDE
36         {
37                 return ConvToNum<intptr_t>(their_param) < ConvToNum<intptr_t>(our_param);
38         }
39
40         ModeAction OnSet(User* source, Channel* chan, std::string& parameter) CXX11_OVERRIDE;
41         void OnUnset(User* source, Channel* chan) CXX11_OVERRIDE;
42
43         void SerializeParam(Channel* chan, intptr_t n, std::string& out)
44         {
45                 out += ConvToStr(n);
46         }
47 };
48
49 class ModuleDelayMsg
50         : public Module
51         , public CTCTags::EventListener
52 {
53  private:
54         DelayMsgMode djm;
55         bool allownotice;
56         ModResult HandleMessage(User* user, const MessageTarget& target, bool notice);
57
58  public:
59         ModuleDelayMsg()
60                 : CTCTags::EventListener(this)
61                 , djm(this)
62         {
63         }
64
65         Version GetVersion() CXX11_OVERRIDE;
66         void OnUserJoin(Membership* memb, bool sync, bool created, CUList&) CXX11_OVERRIDE;
67         ModResult OnUserPreMessage(User* user, const MessageTarget& target, MessageDetails& details) CXX11_OVERRIDE;
68         ModResult OnUserPreTagMessage(User* user, const MessageTarget& target, CTCTags::TagMessageDetails& details) CXX11_OVERRIDE;
69         void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE;
70 };
71
72 ModeAction DelayMsgMode::OnSet(User* source, Channel* chan, std::string& parameter)
73 {
74         // Setting a new limit, sanity check
75         intptr_t limit = ConvToNum<intptr_t>(parameter);
76         if (limit <= 0)
77                 limit = 1;
78
79         ext.set(chan, limit);
80         return MODEACTION_ALLOW;
81 }
82
83 void DelayMsgMode::OnUnset(User* source, Channel* chan)
84 {
85         /*
86          * Clean up metadata
87          */
88         const Channel::MemberMap& users = chan->GetUsers();
89         for (Channel::MemberMap::const_iterator n = users.begin(); n != users.end(); ++n)
90                 jointime.set(n->second, 0);
91 }
92
93 Version ModuleDelayMsg::GetVersion()
94 {
95         return Version("Provides channel mode +d <int>, to deny messages to a channel until <int> seconds have passed", VF_VENDOR);
96 }
97
98 void ModuleDelayMsg::OnUserJoin(Membership* memb, bool sync, bool created, CUList&)
99 {
100         if ((IS_LOCAL(memb->user)) && (memb->chan->IsModeSet(djm)))
101         {
102                 djm.jointime.set(memb, ServerInstance->Time());
103         }
104 }
105
106 ModResult ModuleDelayMsg::OnUserPreMessage(User* user, const MessageTarget& target, MessageDetails& details)
107 {
108         return HandleMessage(user, target, details.type == MSG_NOTICE);
109 }
110
111 ModResult ModuleDelayMsg::OnUserPreTagMessage(User* user, const MessageTarget& target, CTCTags::TagMessageDetails& details)
112 {
113         return HandleMessage(user, target, false);
114 }
115
116 ModResult ModuleDelayMsg::HandleMessage(User* user, const MessageTarget& target, bool notice)
117 {
118         if (!IS_LOCAL(user))
119                 return MOD_RES_PASSTHRU;
120
121         if ((target.type != MessageTarget::TYPE_CHANNEL) || ((!allownotice) && (notice)))
122                 return MOD_RES_PASSTHRU;
123
124         Channel* channel = target.Get<Channel>();
125         Membership* memb = channel->GetUser(user);
126
127         if (!memb)
128                 return MOD_RES_PASSTHRU;
129
130         time_t ts = djm.jointime.get(memb);
131
132         if (ts == 0)
133                 return MOD_RES_PASSTHRU;
134
135         int len = djm.ext.get(channel);
136
137         if ((ts + len) > ServerInstance->Time())
138         {
139                 if (channel->GetPrefixValue(user) < VOICE_VALUE)
140                 {
141                         user->WriteNumeric(ERR_CANNOTSENDTOCHAN, channel->name, InspIRCd::Format("You must wait %d seconds after joining to send to the channel (+d is set)", len));
142                         return MOD_RES_DENY;
143                 }
144         }
145         else
146         {
147                 /* Timer has expired, we can stop checking now */
148                 djm.jointime.set(memb, 0);
149         }
150         return MOD_RES_PASSTHRU;
151 }
152
153 void ModuleDelayMsg::ReadConfig(ConfigStatus& status)
154 {
155         ConfigTag* tag = ServerInstance->Config->ConfValue("delaymsg");
156         allownotice = tag->getBool("allownotice", true);
157 }
158
159 MODULE_INIT(ModuleDelayMsg)