]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_delaymsg.cpp
5805d4bad0c00a7cb9d01b7fe259b217a1c673fb
[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         }
33
34         bool ResolveModeConflict(std::string& their_param, const std::string& our_param, Channel*) CXX11_OVERRIDE
35         {
36                 return (atoi(their_param.c_str()) < atoi(our_param.c_str()));
37         }
38
39         ModeAction OnSet(User* source, Channel* chan, std::string& parameter) CXX11_OVERRIDE;
40         void OnUnset(User* source, Channel* chan) CXX11_OVERRIDE;
41
42         void SerializeParam(Channel* chan, intptr_t n, std::string& out)
43         {
44                 out += ConvToStr(n);
45         }
46 };
47
48 class ModuleDelayMsg
49         : public Module
50         , public CTCTags::EventListener 
51 {
52  private:
53         DelayMsgMode djm;
54         bool allownotice;
55         ModResult HandleMessage(User* user, const MessageTarget& target, bool notice);
56
57  public:
58         ModuleDelayMsg()
59                 : CTCTags::EventListener(this)
60                 , djm(this)
61         {
62         }
63
64         Version GetVersion() CXX11_OVERRIDE;
65         void OnUserJoin(Membership* memb, bool sync, bool created, CUList&) CXX11_OVERRIDE;
66         ModResult OnUserPreMessage(User* user, const MessageTarget& target, MessageDetails& details) CXX11_OVERRIDE;
67         ModResult OnUserPreTagMessage(User* user, const MessageTarget& target, CTCTags::TagMessageDetails& details) CXX11_OVERRIDE;
68         void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE;
69 };
70
71 ModeAction DelayMsgMode::OnSet(User* source, Channel* chan, std::string& parameter)
72 {
73         // Setting a new limit, sanity check
74         intptr_t limit = ConvToNum<intptr_t>(parameter);
75         if (limit <= 0)
76                 limit = 1;
77
78         ext.set(chan, limit);
79         return MODEACTION_ALLOW;
80 }
81
82 void DelayMsgMode::OnUnset(User* source, Channel* chan)
83 {
84         /*
85          * Clean up metadata
86          */
87         const Channel::MemberMap& users = chan->GetUsers();
88         for (Channel::MemberMap::const_iterator n = users.begin(); n != users.end(); ++n)
89                 jointime.set(n->second, 0);
90 }
91
92 Version ModuleDelayMsg::GetVersion()
93 {
94         return Version("Provides channelmode +d <int>, to deny messages to a channel until <int> seconds.", VF_VENDOR);
95 }
96
97 void ModuleDelayMsg::OnUserJoin(Membership* memb, bool sync, bool created, CUList&)
98 {
99         if ((IS_LOCAL(memb->user)) && (memb->chan->IsModeSet(djm)))
100         {
101                 djm.jointime.set(memb, ServerInstance->Time());
102         }
103 }
104
105 ModResult ModuleDelayMsg::OnUserPreMessage(User* user, const MessageTarget& target, MessageDetails& details)
106 {
107         return HandleMessage(user, target, details.type == MSG_NOTICE);
108 }
109
110 ModResult ModuleDelayMsg::OnUserPreTagMessage(User* user, const MessageTarget& target, CTCTags::TagMessageDetails& details)
111 {
112         return HandleMessage(user, target, false);
113 }
114
115 ModResult ModuleDelayMsg::HandleMessage(User* user, const MessageTarget& target, bool notice)
116 {
117         if (!IS_LOCAL(user))
118                 return MOD_RES_PASSTHRU;
119
120         if ((target.type != MessageTarget::TYPE_CHANNEL) || ((!allownotice) && (notice)))
121                 return MOD_RES_PASSTHRU;
122
123         Channel* channel = target.Get<Channel>();
124         Membership* memb = channel->GetUser(user);
125
126         if (!memb)
127                 return MOD_RES_PASSTHRU;
128
129         time_t ts = djm.jointime.get(memb);
130
131         if (ts == 0)
132                 return MOD_RES_PASSTHRU;
133
134         int len = djm.ext.get(channel);
135
136         if ((ts + len) > ServerInstance->Time())
137         {
138                 if (channel->GetPrefixValue(user) < VOICE_VALUE)
139                 {
140                         user->WriteNumeric(ERR_CANNOTSENDTOCHAN, channel->name, InspIRCd::Format("You must wait %d seconds after joining to send to channel (+d)", len));
141                         return MOD_RES_DENY;
142                 }
143         }
144         else
145         {
146                 /* Timer has expired, we can stop checking now */
147                 djm.jointime.set(memb, 0);
148         }
149         return MOD_RES_PASSTHRU;
150 }
151
152 void ModuleDelayMsg::ReadConfig(ConfigStatus& status)
153 {
154         ConfigTag* tag = ServerInstance->Config->ConfValue("delaymsg");
155         allownotice = tag->getBool("allownotice", true);
156 }
157
158 MODULE_INIT(ModuleDelayMsg)