anope

- supernets anope source code & configuration
git clone git://git.acid.vegas/anope.git
Log | Files | Refs | Archive | README

ms_read.cpp (6006B)

      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 static ServiceReference<MemoServService> MemoServService("MemoServService", "MemoServ");
     15 
     16 static void rsend_notify(CommandSource &source, MemoInfo *mi, Memo *m, const Anope::string &targ)
     17 {
     18 	/* Only send receipt if memos are allowed */
     19 	if (MemoServService && !Anope::ReadOnly)
     20 	{
     21 		/* Get nick alias for sender */
     22 		const NickAlias *na = NickAlias::Find(m->sender);
     23 
     24 		if (!na)
     25 			return;
     26 
     27 		/* Get nick core for sender */
     28 		const NickCore *nc = na->nc;
     29 
     30 		if (!nc)
     31 			return;
     32 
     33 		/* Text of the memo varies if the recipient was a
     34 		   nick or channel */
     35 		Anope::string text = Anope::printf(Language::Translate(na->nc, _("\002[auto-memo]\002 The memo you sent to %s has been viewed.")), targ.c_str());
     36 
     37 		/* Send notification */
     38 		MemoServService->Send(source.GetNick(), m->sender, text, true);
     39 
     40 		/* Notify recipient of the memo that a notification has
     41 		   been sent to the sender */
     42 		source.Reply(_("A notification memo has been sent to %s informing him/her you have\n"
     43 				"read his/her memo."), nc->display.c_str());
     44 	}
     45 
     46 	/* Remove receipt flag from the original memo */
     47 	m->receipt = false;
     48 }
     49 
     50 class MemoListCallback : public NumberList
     51 {
     52 	CommandSource &source;
     53 	MemoInfo *mi;
     54 	const ChannelInfo *ci;
     55 	bool found;
     56  public:
     57 	MemoListCallback(CommandSource &_source, MemoInfo *_mi, const ChannelInfo *_ci, const Anope::string &numlist) : NumberList(numlist, false), source(_source), mi(_mi), ci(_ci)
     58 	{
     59 		found = false;
     60 	}
     61 
     62 	~MemoListCallback()
     63 	{
     64 		if (!found)
     65 			source.Reply(_("No memos to display."));
     66 	}
     67 
     68 	void HandleNumber(unsigned number) anope_override
     69 	{
     70 		if (!number || number > mi->memos->size())
     71 			return;
     72 
     73 		MemoListCallback::DoRead(source, mi, ci, number - 1);
     74 		found = true;
     75 	}
     76 
     77 	static void DoRead(CommandSource &source, MemoInfo *mi, const ChannelInfo *ci, unsigned index)
     78 	{
     79 		Memo *m = mi->GetMemo(index);
     80 		if (!m)
     81 			return;
     82 
     83 		if (ci)
     84 			source.Reply(_("Memo %d from %s (%s)."), index + 1, m->sender.c_str(), Anope::strftime(m->time, source.GetAccount()).c_str());
     85 		else
     86 			source.Reply(_("Memo %d from %s (%s)."), index + 1, m->sender.c_str(), Anope::strftime(m->time, source.GetAccount()).c_str());
     87 
     88 		BotInfo *bi;
     89 		Anope::string cmd;
     90 		if (Command::FindCommandFromService("memoserv/del", bi, cmd))
     91 		{
     92 			if (ci)
     93 				source.Reply(_("To delete, type: \002%s%s %s %s %d\002"), Config->StrictPrivmsg.c_str(), bi->nick.c_str(), cmd.c_str(), ci->name.c_str(), index + 1);
     94 			else
     95 				source.Reply(_("To delete, type: \002%s%s %s %d\002"), Config->StrictPrivmsg.c_str(), bi->nick.c_str(), cmd.c_str(), index + 1);
     96 		}
     97 
     98 		source.Reply("%s", m->text.c_str());
     99 		m->unread = false;
    100 
    101 		/* Check if a receipt notification was requested */
    102 		if (m->receipt)
    103 			rsend_notify(source, mi, m, ci ? ci->name : source.GetNick());
    104 	}
    105 };
    106 
    107 class CommandMSRead : public Command
    108 {
    109  public:
    110 	CommandMSRead(Module *creator) : Command(creator, "memoserv/read", 1, 2)
    111 	{
    112 		this->SetDesc(_("Read a memo or memos"));
    113 		this->SetSyntax(_("[\037channel\037] {\037num\037 | \037list\037 | LAST | NEW | ALL}"));
    114 	}
    115 
    116 	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
    117 	{
    118 
    119 		MemoInfo *mi;
    120 		ChannelInfo *ci = NULL;
    121 		Anope::string numstr = params[0], chan;
    122 
    123 		if (!numstr.empty() && numstr[0] == '#')
    124 		{
    125 			chan = numstr;
    126 			numstr = params.size() > 1 ? params[1] : "";
    127 
    128 			ci = ChannelInfo::Find(chan);
    129 			if (!ci)
    130 			{
    131 				source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str());
    132 				return;
    133 			}
    134 			else if (!source.AccessFor(ci).HasPriv("MEMO"))
    135 			{
    136 				source.Reply(ACCESS_DENIED);
    137 				return;
    138 			}
    139 			mi = &ci->memos;
    140 		}
    141 		else
    142 			mi = &source.nc->memos;
    143 
    144 		if (numstr.empty() || (!numstr.equals_ci("LAST") && !numstr.equals_ci("NEW") && !numstr.equals_ci("ALL") && numstr.find_first_not_of("0123456789.,-") != Anope::string::npos))
    145 			this->OnSyntaxError(source, numstr);
    146 		else if (mi->memos->empty())
    147 		{
    148 			if (!chan.empty())
    149 				source.Reply(MEMO_X_HAS_NO_MEMOS, chan.c_str());
    150 			else
    151 				source.Reply(MEMO_HAVE_NO_MEMOS);
    152 		}
    153 		else
    154 		{
    155 			int i, end;
    156 
    157 			if (numstr.equals_ci("NEW"))
    158 			{
    159 				int readcount = 0;
    160 				for (i = 0, end = mi->memos->size(); i < end; ++i)
    161 					if (mi->GetMemo(i)->unread)
    162 					{
    163 						MemoListCallback::DoRead(source, mi, ci, i);
    164 						++readcount;
    165 					}
    166 				if (!readcount)
    167 				{
    168 					if (!chan.empty())
    169 						source.Reply(MEMO_X_HAS_NO_NEW_MEMOS, chan.c_str());
    170 					else
    171 						source.Reply(MEMO_HAVE_NO_NEW_MEMOS);
    172 				}
    173 			}
    174 			else if (numstr.equals_ci("LAST"))
    175 			{
    176 				for (i = 0, end = mi->memos->size() - 1; i < end; ++i);
    177 				MemoListCallback::DoRead(source, mi, ci, i);
    178 			}
    179 			else if (numstr.equals_ci("ALL"))
    180 			{
    181 				for (i = 0, end = mi->memos->size(); i < end; ++i)
    182 				{
    183 					MemoListCallback::DoRead(source, mi, ci, i);
    184 				}
    185 			}
    186 			else /* number[s] */
    187 			{
    188 				MemoListCallback list(source, mi, ci, numstr);
    189 				list.Process();
    190 			}
    191 		}
    192 		return;
    193 	}
    194 
    195 	bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
    196 	{
    197 		this->SendSyntax(source);
    198 		source.Reply(" ");
    199 		source.Reply(_("Sends you the text of the memos specified. If LAST is\n"
    200 				"given, sends you the memo you most recently received. If\n"
    201 				"NEW is given, sends you all of your new memos.  If ALL is\n"
    202 				"given, sends you all of your memos. Otherwise, sends you\n"
    203 				"memo number \037num\037. You can also give a list of numbers,\n"
    204 				"as in this example:\n"
    205 				" \n"
    206 				"   \002READ 2-5,7-9\002\n"
    207 				"      Displays memos numbered 2 through 5 and 7 through 9."));
    208 		return true;
    209 	}
    210 };
    211 
    212 class MSRead : public Module
    213 {
    214 	CommandMSRead commandmsread;
    215 
    216  public:
    217 	MSRead(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
    218 		commandmsread(this)
    219 	{
    220 
    221 	}
    222 };
    223 
    224 MODULE_INIT(MSRead)