anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
memoserv.cpp (7435B)
1 /* MemoServ core functions 2 * 3 * (C) 2003-2022 Anope Team 4 * Contact us at team@anope.org 5 * 6 * Please read COPYING and README for further details. 7 * 8 * Based on the original code of Epona by Lara. 9 * Based on the original code of Services by Andy Church. 10 */ 11 12 #include "module.h" 13 14 class MemoServCore : public Module, public MemoServService 15 { 16 Reference<BotInfo> MemoServ; 17 18 bool SendMemoMail(NickCore *nc, MemoInfo *mi, Memo *m) 19 { 20 Anope::string subject = Language::Translate(nc, Config->GetBlock("mail")->Get<const Anope::string>("memo_subject").c_str()), 21 message = Language::Translate(Config->GetBlock("mail")->Get<const Anope::string>("memo_message").c_str()); 22 23 subject = subject.replace_all_cs("%n", nc->display); 24 subject = subject.replace_all_cs("%s", m->sender); 25 subject = subject.replace_all_cs("%d", stringify(mi->GetIndex(m) + 1)); 26 subject = subject.replace_all_cs("%t", m->text); 27 subject = subject.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname")); 28 29 message = message.replace_all_cs("%n", nc->display); 30 message = message.replace_all_cs("%s", m->sender); 31 message = message.replace_all_cs("%d", stringify(mi->GetIndex(m) + 1)); 32 message = message.replace_all_cs("%t", m->text); 33 message = message.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname")); 34 35 return Mail::Send(nc, subject, message); 36 } 37 38 public: 39 MemoServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR), 40 MemoServService(this) 41 { 42 } 43 44 MemoResult Send(const Anope::string &source, const Anope::string &target, const Anope::string &message, bool force) anope_override 45 { 46 bool ischan; 47 MemoInfo *mi = MemoInfo::GetMemoInfo(target, ischan); 48 49 if (mi == NULL) 50 return MEMO_INVALID_TARGET; 51 52 Anope::string sender_display = source; 53 54 User *sender = User::Find(source, true); 55 if (sender != NULL) 56 { 57 if (!sender->HasPriv("memoserv/no-limit") && !force) 58 { 59 time_t send_delay = Config->GetModule("memoserv")->Get<time_t>("senddelay"); 60 if (send_delay > 0 && sender->lastmemosend + send_delay > Anope::CurTime) 61 return MEMO_TOO_FAST; 62 else if (!mi->memomax) 63 return MEMO_TARGET_FULL; 64 else if (mi->memomax > 0 && mi->memos->size() >= static_cast<unsigned>(mi->memomax)) 65 return MEMO_TARGET_FULL; 66 else if (mi->HasIgnore(sender)) 67 return MEMO_SUCCESS; 68 } 69 70 NickCore *acc = sender->Account(); 71 if (acc != NULL) 72 { 73 sender_display = acc->display; 74 } 75 } 76 77 if (sender != NULL) 78 sender->lastmemosend = Anope::CurTime; 79 80 Memo *m = new Memo(); 81 m->mi = mi; 82 mi->memos->push_back(m); 83 m->owner = target; 84 m->sender = sender_display; 85 m->time = Anope::CurTime; 86 m->text = message; 87 m->unread = true; 88 89 FOREACH_MOD(OnMemoSend, (source, target, mi, m)); 90 91 if (ischan) 92 { 93 ChannelInfo *ci = ChannelInfo::Find(target); 94 95 if (ci->c) 96 { 97 for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it) 98 { 99 ChanUserContainer *cu = it->second; 100 101 if (ci->AccessFor(cu->user).HasPriv("MEMO")) 102 { 103 if (cu->user->Account() && cu->user->Account()->HasExt("MEMO_RECEIVE")) 104 cu->user->SendMessage(MemoServ, MEMO_NEW_X_MEMO_ARRIVED, ci->name.c_str(), Config->StrictPrivmsg.c_str(), MemoServ->nick.c_str(), ci->name.c_str(), mi->memos->size()); 105 } 106 } 107 } 108 } 109 else 110 { 111 NickCore *nc = NickAlias::Find(target)->nc; 112 113 if (nc->HasExt("MEMO_RECEIVE")) 114 { 115 for (unsigned i = 0; i < nc->aliases->size(); ++i) 116 { 117 const NickAlias *na = nc->aliases->at(i); 118 User *user = User::Find(na->nick, true); 119 if (user && user->IsIdentified()) 120 user->SendMessage(MemoServ, MEMO_NEW_MEMO_ARRIVED, source.c_str(), Config->StrictPrivmsg.c_str(), MemoServ->nick.c_str(), mi->memos->size()); 121 } 122 } 123 124 /* let's get out the mail if set in the nickcore - certus */ 125 if (nc->HasExt("MEMO_MAIL")) 126 SendMemoMail(nc, mi, m); 127 } 128 129 return MEMO_SUCCESS; 130 } 131 132 void Check(User *u) anope_override 133 { 134 const NickCore *nc = u->Account(); 135 if (!nc) 136 return; 137 138 unsigned i = 0, end = nc->memos.memos->size(), newcnt = 0; 139 for (; i < end; ++i) 140 if (nc->memos.GetMemo(i)->unread) 141 ++newcnt; 142 if (newcnt > 0) 143 u->SendMessage(MemoServ, newcnt == 1 ? _("You have 1 new memo.") : _("You have %d new memos."), newcnt); 144 if (nc->memos.memomax > 0 && nc->memos.memos->size() >= static_cast<unsigned>(nc->memos.memomax)) 145 { 146 if (nc->memos.memos->size() > static_cast<unsigned>(nc->memos.memomax)) 147 u->SendMessage(MemoServ, _("You are over your maximum number of memos (%d). You will be unable to receive any new memos until you delete some of your current ones."), nc->memos.memomax); 148 else 149 u->SendMessage(MemoServ, _("You have reached your maximum number of memos (%d). You will be unable to receive any new memos until you delete some of your current ones."), nc->memos.memomax); 150 } 151 } 152 153 void OnReload(Configuration::Conf *conf) anope_override 154 { 155 const Anope::string &msnick = conf->GetModule(this)->Get<const Anope::string>("client"); 156 157 if (msnick.empty()) 158 throw ConfigException(Module::name + ": <client> must be defined"); 159 160 BotInfo *bi = BotInfo::Find(msnick, true); 161 if (!bi) 162 throw ConfigException(Module::name + ": no bot named " + msnick); 163 164 MemoServ = bi; 165 } 166 167 void OnNickCoreCreate(NickCore *nc) anope_override 168 { 169 nc->memos.memomax = Config->GetModule(this)->Get<int>("maxmemos"); 170 } 171 172 void OnCreateChan(ChannelInfo *ci) anope_override 173 { 174 ci->memos.memomax = Config->GetModule(this)->Get<int>("maxmemos"); 175 } 176 177 void OnBotDelete(BotInfo *bi) anope_override 178 { 179 if (bi == MemoServ) 180 MemoServ = NULL; 181 } 182 183 void OnNickIdentify(User *u) anope_override 184 { 185 this->Check(u); 186 } 187 188 void OnJoinChannel(User *u, Channel *c) anope_override 189 { 190 if (c->ci && !c->ci->memos.memos->empty() && c->ci->AccessFor(u).HasPriv("MEMO")) 191 { 192 if (c->ci->memos.memos->size() == 1) 193 u->SendMessage(MemoServ, _("There is \002%d\002 memo on channel %s."), c->ci->memos.memos->size(), c->ci->name.c_str()); 194 else 195 u->SendMessage(MemoServ, _("There are \002%d\002 memos on channel %s."), c->ci->memos.memos->size(), c->ci->name.c_str()); 196 } 197 } 198 199 void OnUserAway(User *u, const Anope::string &message) anope_override 200 { 201 if (message.empty()) 202 this->Check(u); 203 } 204 205 void OnNickUpdate(User *u) anope_override 206 { 207 this->Check(u); 208 } 209 210 EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 211 { 212 if (!params.empty() || source.c || source.service != *MemoServ) 213 return EVENT_CONTINUE; 214 source.Reply(_("\002%s\002 is a utility allowing IRC users to send short\n" 215 "messages to other IRC users, whether they are online at\n" 216 "the time or not, or to channels(*). Both the sender's\n" 217 "nickname and the target nickname or channel must be\n" 218 "registered in order to send a memo.\n" 219 "%s's commands include:"), MemoServ->nick.c_str(), MemoServ->nick.c_str()); 220 return EVENT_CONTINUE; 221 } 222 223 void OnPostHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 224 { 225 if (!params.empty() || source.c || source.service != *MemoServ) 226 return; 227 source.Reply(_(" \n" 228 "Type \002%s%s HELP \037command\037\002 for help on any of the\n" 229 "above commands."), Config->StrictPrivmsg.c_str(), MemoServ->nick.c_str()); 230 } 231 }; 232 233 MODULE_INIT(MemoServCore)