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> &params) 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> &params) 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)