2 * InspIRCd -- Internet Relay Chat Daemon
4 * Copyright (C) 2018-2019 Sadie Powell <sadie@witchery.services>
5 * Copyright (C) 2015 Attila Molnar <attilamolnar@hush.com>
7 * This file is part of InspIRCd. InspIRCd is free software: you can
8 * redistribute it and/or modify it under the terms of the GNU General Public
9 * License as published by the Free Software Foundation, version 2.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 class InviteExpireTimer : public Timer
27 Invite::Invite* const inv;
29 bool Tick(time_t currtime) CXX11_OVERRIDE;
32 InviteExpireTimer(Invite::Invite* invite, time_t timeout);
35 static Invite::APIImpl* apiimpl;
37 void RemoveInvite(Invite::Invite* inv, bool remove_user, bool remove_chan)
39 apiimpl->Destruct(inv, remove_user, remove_chan);
42 void UnserializeInvite(LocalUser* user, const std::string& str)
44 apiimpl->Unserialize(user, str);
47 Invite::APIBase::APIBase(Module* parent)
48 : DataProvider(parent, "core_channel_invite")
52 Invite::APIImpl::APIImpl(Module* parent)
54 , userext(parent, "invite_user")
55 , chanext(parent, "invite_chan")
60 void Invite::APIImpl::Destruct(Invite* inv, bool remove_user, bool remove_chan)
62 Store<LocalUser>* ustore = userext.get(inv->user);
65 ustore->invites.erase(inv);
66 if ((remove_user) && (ustore->invites.empty()))
67 userext.unset(inv->user);
70 Store<Channel>* cstore = chanext.get(inv->chan);
73 cstore->invites.erase(inv);
74 if ((remove_chan) && (cstore->invites.empty()))
75 chanext.unset(inv->chan);
81 bool Invite::APIImpl::Remove(LocalUser* user, Channel* chan)
83 Invite* inv = Find(user, chan);
92 void Invite::APIImpl::Create(LocalUser* user, Channel* chan, time_t timeout)
94 if ((timeout != 0) && (ServerInstance->Time() >= timeout))
95 // Expired, don't bother
98 ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Invite::APIImpl::Create(): user=%s chan=%s timeout=%lu", user->uuid.c_str(), chan->name.c_str(), (unsigned long)timeout);
100 Invite* inv = Find(user, chan);
103 // We only ever extend invites, so nothing to do if the existing one is not timed
107 ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Invite::APIImpl::Create(): changing expiration in %p", (void*) inv);
110 // Convert timed invite to non-expiring
111 delete inv->expiretimer;
112 inv->expiretimer = NULL;
114 else if (inv->expiretimer->GetTrigger() >= ServerInstance->Time() + timeout)
116 // New expiration time is further than the current, extend the expiration
117 inv->expiretimer->SetInterval(timeout - ServerInstance->Time());
122 inv = new Invite(user, chan);
125 inv->expiretimer = new InviteExpireTimer(inv, timeout - ServerInstance->Time());
126 ServerInstance->Timers.AddTimer(inv->expiretimer);
129 userext.get(user, true)->invites.push_front(inv);
130 chanext.get(chan, true)->invites.push_front(inv);
131 ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Invite::APIImpl::Create(): created new Invite %p", (void*) inv);
135 Invite::Invite* Invite::APIImpl::Find(LocalUser* user, Channel* chan)
137 const List* list = APIImpl::GetList(user);
141 for (List::iterator i = list->begin(); i != list->end(); ++i)
144 if (inv->chan == chan)
151 const Invite::List* Invite::APIImpl::GetList(LocalUser* user)
153 Store<LocalUser>* list = userext.get(user);
155 return &list->invites;
159 void Invite::APIImpl::Unserialize(LocalUser* user, const std::string& value)
161 irc::spacesepstream ss(value);
162 for (std::string channame, exptime; (ss.GetToken(channame) && ss.GetToken(exptime)); )
164 Channel* chan = ServerInstance->FindChan(channame);
166 Create(user, chan, ConvToNum<time_t>(exptime));
170 Invite::Invite::Invite(LocalUser* u, Channel* c)
177 Invite::Invite::~Invite()
180 ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Invite::~ %p", (void*) this);
183 void Invite::Invite::Serialize(bool human, bool show_chans, std::string& out)
186 out.append(this->chan->name);
188 out.append(human ? user->nick : user->uuid);
192 out.append(ConvToStr(expiretimer->GetTrigger()));
198 InviteExpireTimer::InviteExpireTimer(Invite::Invite* invite, time_t timeout)
204 bool InviteExpireTimer::Tick(time_t currtime)
206 ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "InviteExpireTimer::Tick(): expired %p", (void*) inv);
207 apiimpl->Destruct(inv);