diff options
| author | Adam <Adam@anope.org> | 2015-12-14 16:52:24 -0500 |
|---|---|---|
| committer | Adam <Adam@anope.org> | 2015-12-14 16:52:24 -0500 |
| commit | 6302f980fe6dad83aab7d2dc1046dadea5ffd939 (patch) | |
| tree | 4c27d33f55fc32ce34827977932dac4b3e5ceedd /modules/memoserv | |
| parent | 64dac60071fab652745a6e7a06cf6b7bdbbd3625 (diff) | |
New source tree structure for modules. From commands/cs_access => chanserv/access etc.
Diffstat (limited to 'modules/memoserv')
27 files changed, 2248 insertions, 0 deletions
diff --git a/modules/memoserv/CMakeLists.txt b/modules/memoserv/CMakeLists.txt new file mode 100644 index 000000000..cd225a94d --- /dev/null +++ b/modules/memoserv/CMakeLists.txt @@ -0,0 +1 @@ +build_modules(${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/modules/memoserv/cancel.cpp b/modules/memoserv/cancel.cpp new file mode 100644 index 000000000..e3da82581 --- /dev/null +++ b/modules/memoserv/cancel.cpp @@ -0,0 +1,91 @@ +/* MemoServ core functions + * + * (C) 2003-2014 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +#include "module.h" +#include "modules/memoserv.h" + +class CommandMSCancel : public Command +{ + public: + CommandMSCancel(Module *creator) : Command(creator, "memoserv/cancel", 1, 1) + { + this->SetDesc(_("Cancel the last memo you sent")); + this->SetSyntax(_("{\037user\037 | \037channel\037}")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override + { + if (Anope::ReadOnly) + { + source.Reply(_("Services are in read-only mode.")); + return; + } + + const Anope::string &nname = params[0]; + + bool ischan, isregistered; + MemoServ::MemoInfo *mi = MemoServ::service->GetMemoInfo(name, ischan, isregistered, false); + + if (!isregistered) + { + if (ischan) + source.Reply(_("Channel \002{0}\002 isn't registered."), nname); + else + source.Reply(_("\002{0}\002 isn't registered."), nname); + } + else + { + ChanServ::Channel *ci = NULL; + NickServ::Nick *na = NULL; + if (ischan) + ci = ChanServ::Find(nname); + else + na = NickServ::FindNick(nname); + if (mi) + { + auto memos = mi->GetMemos(); + for (int i = memos.size() - 1; i >= 0; --i) + { + MemoServ::Memo *m = memos[i]; + if (m->GetUnread() && source.nc->GetDisplay().equals_ci(m->GetSender())) + { + if (MemoServ::Event::OnMemoDel) + MemoServ::Event::OnMemoDel(&MemoServ::Event::MemoDel::OnMemoDel, ischan ? ci->GetName() : na->GetAccount()->GetDisplay(), mi, m); + mi->Del(i); + source.Reply(_("Your last memo to \002{0}\002 has been cancelled."), nname); + return; + } + } + } + + source.Reply(_("No memo to \002{0}\002 was cancelable."), nname); + } + } + + bool OnHelp(CommandSource &source, const Anope::string &subcommand) override + { + source.Reply(_("Cancels the last memo you sent to \037user\037, provided it has not yet been read.")); + return true; + } +}; + +class MSCancel : public Module +{ + CommandMSCancel commandmscancel; + + public: + MSCancel(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR) + , commandmscancel(this) + { + } +}; + +MODULE_INIT(MSCancel) diff --git a/modules/memoserv/check.cpp b/modules/memoserv/check.cpp new file mode 100644 index 000000000..75a8ee3d0 --- /dev/null +++ b/modules/memoserv/check.cpp @@ -0,0 +1,80 @@ +/* MemoServ core functions + * + * (C) 2003-2014 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +#include "module.h" + +class CommandMSCheck : public Command +{ + public: + CommandMSCheck(Module *creator) : Command(creator, "memoserv/check", 1, 1) + { + this->SetDesc(_("Checks if last memo to a user was read")); + this->SetSyntax(_("\037user\037")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override + { + const Anope::string &recipient = params[0]; + + bool found = false; + + NickServ::Nick *na = NickServ::FindNick(recipient); + if (!na) + { + source.Reply(_("\002{0}\002 isn't registered."), recipient); + return; + } + + MemoServ::MemoInfo *mi = na->GetAccount()->GetMemos(); + + if (mi) + /* find the last memo */ + for (unsigned i = mi->GetMemos().size(); i > 0; --i) + { + MemoServ::Memo *m = mi->GetMemo(i - 1); + NickServ::Nick *na2 = NickServ::FindNick(m->GetSender()); + + if (na2 != NULL && na2->GetAccount() == source.GetAccount()) + { + found = true; /* Yes, we've found the memo */ + + if (m->GetUnread()) + source.Reply(_("The last memo you sent to \002{0}\002 (sent on \002{1}\002) has not yet been read."), na->GetNick(), Anope::strftime(m->GetTime(), source.GetAccount())); + else + source.Reply(_("The last memo you sent to \002{0}\002 (sent on \002{1}\002) has been read."), na->GetNick(), Anope::strftime(m->GetTime(), source.GetAccount())); + break; + } + } + + if (!found) + source.Reply(_("\002{0}\002 doesn't have a memo from you."), na->GetNick()); + } + + bool OnHelp(CommandSource &source, const Anope::string &subcommand) override + { + source.Reply(_("Checks whether the last memo you sent to \037user\037 has been read or not.")); + return true; + } +}; + +class MSCheck : public Module +{ + CommandMSCheck commandmscheck; + + public: + MSCheck(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR) + , commandmscheck(this) + { + + } +}; + +MODULE_INIT(MSCheck) diff --git a/modules/memoserv/del.cpp b/modules/memoserv/del.cpp new file mode 100644 index 000000000..79af11adc --- /dev/null +++ b/modules/memoserv/del.cpp @@ -0,0 +1,148 @@ +/* MemoServ core functions + * + * (C) 2003-2014 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +#include "module.h" +#include "modules/memoserv.h" + +class CommandMSDel : public Command +{ + public: + CommandMSDel(Module *creator) : Command(creator, "memoserv/del", 0, 2) + { + this->SetDesc(_("Delete a memo or memos")); + this->SetSyntax(_("[\037channel\037] {\037num\037 | \037list\037 | LAST | ALL}")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override + { + if (Anope::ReadOnly) + { + source.Reply(_("Services are in read-only mode.")); + return; + } + + MemoServ::MemoInfo *mi; + ChanServ::Channel *ci = NULL; + Anope::string numstr = !params.empty() ? params[0] : "", chan; + + if (!numstr.empty() && numstr[0] == '#') + { + chan = numstr; + numstr = params.size() > 1 ? params[1] : ""; + + ci = ChanServ::Find(chan); + if (!ci) + { + source.Reply(_("Channel \002{0}\002 isn't registered."), chan); + return; + } + + if (!source.AccessFor(ci).HasPriv("MEMO")) + { + source.Reply(_("Access denied. You do not have privilege \002{0}\002 on \002{1}\002."), "MEMO", ci->GetName()); + return; + } + + mi = ci->GetMemos(); + } + else + mi = source.nc->GetMemos(); + + if (numstr.empty() || (!isdigit(numstr[0]) && !numstr.equals_ci("ALL") && !numstr.equals_ci("LAST"))) + { + this->OnSyntaxError(source, numstr); + return; + } + + if (!mi || mi->GetMemos().empty()) + { + if (!chan.empty()) + source.Reply(_("\002{0}\002 has no memos."), chan); + else + source.Reply(_("You have no memos.")); + return; + } + + auto memos = mi->GetMemos(); + + if (isdigit(numstr[0])) + { + NumberList(numstr, true, + [&](unsigned int number) + { + if (!number || number > memos.size()) + return; + + if (MemoServ::Event::OnMemoDel) + MemoServ::Event::OnMemoDel(&MemoServ::Event::MemoDel::OnMemoDel, ci ? ci->GetName() : source.nc->GetDisplay(), mi, mi->GetMemo(number - 1)); + + mi->Del(number - 1); + source.Reply(_("Memo \002{0}\002 has been deleted."), number); + }, + [](){}); + } + else if (numstr.equals_ci("LAST")) + { + /* Delete last memo. */ + if (MemoServ::Event::OnMemoDel) + MemoServ::Event::OnMemoDel(&MemoServ::Event::MemoDel::OnMemoDel, ci ? ci->GetName() : source.nc->GetDisplay(), mi, mi->GetMemo(memos.size() - 1)); + mi->Del(memos.size() - 1); + source.Reply(_("Memo \002{0}\002 has been deleted."), memos.size() + 1); + } + else + { + /* Delete all memos. */ + std::for_each(memos.begin(), memos.end(), + [&](MemoServ::Memo *m) + { + if (MemoServ::Event::OnMemoDel) + MemoServ::Event::OnMemoDel(&MemoServ::Event::MemoDel::OnMemoDel, ci ? ci->GetName() : source.nc->GetDisplay(), mi, m); + delete m; + }); + if (!chan.empty()) + source.Reply(_("All memos for channel \002{0}\002 have been deleted."), chan); + else + source.Reply(_("All of your memos have been deleted.")); + } + } + + bool OnHelp(CommandSource &source, const Anope::string &subcommand) override + { + source.Reply(_("Deletes the specified memo or memos." + " You can supply multiple memo numbers or ranges of numbers instead of a single number, as in the second example below." + " If \002LAST\002 is given, the last memo will be deleted." + " If \002ALL\002 is given, deletes all of your memos.\n" + "\n" + "Examples:\n" + "\n" + " {0} 1\n" + " Deletes your first memo.\n" + "\n" + " {0} 2-5,7-9\n" + " Deletes memos numbered 2 through 5 and 7 through 9."), + source.command); + return true; + } +}; + +class MSDel : public Module +{ + CommandMSDel commandmsdel; + + public: + MSDel(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR) + , commandmsdel(this) + { + + } +}; + +MODULE_INIT(MSDel) diff --git a/modules/memoserv/ignore.cpp b/modules/memoserv/ignore.cpp new file mode 100644 index 000000000..c454444ea --- /dev/null +++ b/modules/memoserv/ignore.cpp @@ -0,0 +1,147 @@ +/* MemoServ core functions + * + * (C) 2003-2014 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +#include "module.h" + +class CommandMSIgnore : public Command +{ + public: + CommandMSIgnore(Module *creator) : Command(creator, "memoserv/ignore", 1, 3) + { + this->SetDesc(_("Manage the memo ignore list")); + this->SetSyntax(_("[\037channel\037] ADD \037entry\037")); + this->SetSyntax(_("[\037channel\037] DEL \037entry\037")); + this->SetSyntax(_("[\037channel\037] LIST")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override + { + if (Anope::ReadOnly) + { + source.Reply(_("Services are in read-only mode.")); + return; + } + + if (!MemoServ::service) + return; + + Anope::string channel = params[0]; + Anope::string command = (params.size() > 1 ? params[1] : ""); + Anope::string param = (params.size() > 2 ? params[2] : ""); + + if (channel[0] != '#') + { + param = command; + command = channel; + channel = source.GetNick(); + } + + bool ischan, isregistered; + MemoServ::MemoInfo *mi = MemoServ::service->GetMemoInfo(channel, ischan, isregistered, true); + ChanServ::Channel *ci = ChanServ::Find(channel); + if (!isregistered) + { + if (ischan) + source.Reply(_("Channel \002{0}\002 isn't registered."), channel); + else + source.Reply(_("\002{0}\002 isn't registered."), channel); + return; + } + + if (ischan && !source.AccessFor(ci).HasPriv("MEMO")) + { + source.Reply(_("Access denied. You do not have privilege \002{0}\002 on \002{1}\002."), "MEMO", ci->GetName()); + return; + } + + auto ignores = mi->GetIgnores(); + + if (command.equals_ci("ADD") && !param.empty()) + { + if (ignores.size() >= Config->GetModule(this->owner)->Get<unsigned>("max", "32")) + { + source.Reply(_("Sorry, the memo ignore list for \002{0}\002 is full."), channel); + return; + } + + for (MemoServ::Ignore *ign : ignores) + if (ign->GetMask().equals_ci(param)) + { + source.Reply(_("\002{0}\002 is already on your memo ignore list."), param); + return; + } + + MemoServ::Ignore *ign = MemoServ::service->CreateIgnore(); + ign->SetMemoInfo(mi); + ign->SetMask(param); + + source.Reply(_("\002{0}\002 has been added to your memo ignore list."), param); + } + else if (command.equals_ci("DEL") && !param.empty()) + { + for (MemoServ::Ignore *ign : ignores) + if (ign->GetMask().equals_ci(param)) + { + delete ign; + source.Reply(_("\002{0}\002 has been removed from your memo ignore list."), param); + return; + } + + source.Reply(_("\002{0}\002 is not on your memo ignore list."), param); + } + else if (command.equals_ci("LIST")) + { + if (ignores.empty()) + { + source.Reply(_("Your memo ignore list is empty.")); + return; + } + ListFormatter list(source.GetAccount()); + list.AddColumn(_("Mask")); + for (MemoServ::Ignore *ign : ignores) + { + ListFormatter::ListEntry entry; + entry["Mask"] = ign->GetMask(); + list.AddEntry(entry); + } + + source.Reply(_("Memo ignore list:")); + + std::vector<Anope::string> replies; + list.Process(replies); + + for (unsigned i = 0; i < replies.size(); ++i) + source.Reply(replies[i]); + } + else + this->OnSyntaxError(source, ""); + } + + bool OnHelp(CommandSource &source, const Anope::string &subcommand) override + { + source.Reply(_("Allows you to ignore users from memoing you or a channel." + " If someone on the memo ignore list tries to memo you or a channel, they will not be told that you have them ignored.")); + return true; + } +}; + +class MSIgnore : public Module +{ + CommandMSIgnore commandmsignore; + + public: + MSIgnore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR) + , commandmsignore(this) + { + } +}; + +MODULE_INIT(MSIgnore) diff --git a/modules/memoserv/info.cpp b/modules/memoserv/info.cpp new file mode 100644 index 000000000..d9bee1cb5 --- /dev/null +++ b/modules/memoserv/info.cpp @@ -0,0 +1,203 @@ +/* MemoServ core functions + * + * (C) 2003-2014 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +#include "module.h" + +class CommandMSInfo : public Command +{ + public: + CommandMSInfo(Module *creator) : Command(creator, "memoserv/info", 0, 1) + { + this->SetDesc(_("Displays information about your memos")); + this->SetSyntax(_("[\037user\037 | \037channel\037]")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override + { + NickServ::Account *nc = source.nc; + MemoServ::MemoInfo *mi; + NickServ::Nick *na = NULL; + ChanServ::Channel *ci = NULL; + const Anope::string &nname = !params.empty() ? params[0] : ""; + bool hardmax; + + if (!nname.empty() && nname[0] != '#' && source.HasPriv("memoserv/info")) + { + na = NickServ::FindNick(nname); + if (!na) + { + source.Reply(_("\002{0}\002 isn't registered."), nname); + return; + } + mi = na->GetAccount()->GetMemos(); + hardmax = na->GetAccount()->HasFieldS("MEMO_HARDMAX"); + } + else if (!nname.empty() && nname[0] == '#') + { + ci = ChanServ::Find(nname); + if (!ci) + { + source.Reply(_("Channel \002{0}\002 isn't registered."), nname); + return; + } + + if (!source.AccessFor(ci).HasPriv("MEMO")) + { + source.Reply(_("Access denied. You do not have privilege \002{0}\002 on \002{1}\002."), "MEMO", ci->GetName()); + return; + } + + mi = ci->GetMemos(); + hardmax = ci->HasFieldS("MEMO_HARDMAX"); + } + else if (!nname.empty()) /* It's not a chan and we aren't an oper */ + { + source.Reply(_("Access denied. You do not have the correct operator privilege to see the memo info of \002{0}\002."), nname); + return; + } + else + { + mi = nc->GetMemos(); + hardmax = nc->HasFieldS("MEMO_HARDMAX"); + } + if (!mi) + return; + + auto memos = mi->GetMemos(); + + if (!nname.empty() && (ci || na->GetAccount() != nc)) + { + if (memos.empty()) + source.Reply(_("%s currently has no memos."), nname.c_str()); + else if (memos.size() == 1) + { + if (mi->GetMemo(0)->GetUnread()) + source.Reply(_("\002{0}\002 currently has \0021\002 memo, and it has not yet been read."), nname); + else + source.Reply(_("\002{0}\002 currently has \0021\002 memo."), nname); + } + else + { + unsigned count = 0, i, end; + for (i = 0, end = memos.size(); i < end; ++i) + if (mi->GetMemo(i)->GetUnread()) + ++count; + if (count == memos.size()) + source.Reply(_("\002{0}\002 currently has \002{1]\002 memos; all of them are unread."), nname, count); + else if (!count) + source.Reply(_("\002{0}\002 currently has \002{1}\002 memos."), nname, memos.size()); + else if (count == 1) + source.Reply(_("\002{0}\002 currently has \002{1}\002 memos, of which \0021\002 is unread."), nname, memos.size()); + else + source.Reply(_("\002{0}\002 currently has \002{1]\002 memos, of which \002{2}\002 are unread."), nname, memos.size(), count); + } + if (mi->GetMemoMax() >= 0) + { + if (hardmax) + source.Reply(_("The memo limit of \002{0}\002 is \002{1}\002, and may not be changed."), nname, mi->GetMemoMax()); + else + source.Reply(_("The memo limit of \002{0}\002 is \002{1}\002."), nname, mi->GetMemoMax()); + } + else + source.Reply(_("\002{0}\002 has no memo limit."), nname); + + if (na) + { + if (na->GetAccount()->HasFieldS("MEMO_RECEIVE") && na->GetAccount()->HasFieldS("MEMO_SIGNON")) + source.Reply(_("\002{0}\002 is notified of new memos at logon and when they arrive."), nname); + else if (na->GetAccount()->HasFieldS("MEMO_RECEIVE")) + source.Reply(_("\002{0}\002 is notified when new memos arrive."), nname); + else if (na->GetAccount()->HasFieldS("MEMO_SIGNON")) + source.Reply(_("\002{0}\002 is notified of news memos at logon."), nname); + else + source.Reply(_("\002{0}\002 is not notified of new memos."), nname); + } + } + else + { + if (memos.empty()) + source.Reply(_("You currently have no memos.")); + else if (memos.size() == 1) + { + if (mi->GetMemo(0)->GetUnread()) + source.Reply(_("You currently have \0021\002 memo, and it has not yet been read.")); + else + source.Reply(_("You currently have \0021\002 memo.")); + } + else + { + unsigned count = 0, i, end; + for (i = 0, end = memos.size(); i < end; ++i) + if (mi->GetMemo(i)->GetUnread()) + ++count; + if (count == memos.size()) + source.Reply(_("You currently have \002{0}\002 memos; all of them are unread."), count); + else if (!count) + source.Reply(_("You currently have \002{0}\002 memos."), memos.size()); + else if (count == 1) + source.Reply(_("You currently have \002{0}\002 memos, of which \0021\002 is unread."), memos.size()); + else + source.Reply(_("You currently have \002{0}\002 memos, of which \002{1}\002 are unread."), memos.size(), count); + } + + if (!mi->GetMemoMax()) + { + if (!source.IsServicesOper() && hardmax) + source.Reply(_("Your memo limit is \0020\002; you will not receive any new memos. You cannot change this limit.")); + else + source.Reply(_("Your memo limit is \0020\002; you will not receive any new memos.")); + } + else if (mi->GetMemoMax() > 0) + { + if (!source.IsServicesOper() && hardmax) + source.Reply(_("Your memo limit is \002{0}\002, and may not be changed."), mi->GetMemoMax()); + else + source.Reply(_("Your memo limit is \002{0}\002."), mi->GetMemoMax()); + } + else + source.Reply(_("You have no limit on the number of memos you may keep.")); + + if (nc->HasFieldS("MEMO_RECEIVE") && nc->HasFieldS("MEMO_SIGNON")) + source.Reply(_("You will be notified of new memos at logon and when they arrive.")); + else if (nc->HasFieldS("MEMO_RECEIVE")) + source.Reply(_("You will be notified when new memos arrive.")); + else if (nc->HasFieldS("MEMO_SIGNON")) + source.Reply(_("You will be notified of new memos at logon.")); + else + source.Reply(_("You will not be notified of new memos.")); + } + } + + bool OnHelp(CommandSource &source, const Anope::string &subcommand) override + { + source.Reply(_("Without a parameter, displays information on the number of memos you have, how many of them are unread, and how many total memos you can receive." + " With a parameter, displays the same information for the given \037user\037 or \037channel\037, if you have the appropriate privilege.\n" + "\n" + "Use of this command on a channel requires the \002{0}\002 privilege on \037channel\037."), + source.command); + + return true; + } +}; + +class MSInfo : public Module +{ + CommandMSInfo commandmsinfo; + + public: + MSInfo(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR) + , commandmsinfo(this) + { + + } +}; + +MODULE_INIT(MSInfo) diff --git a/modules/memoserv/list.cpp b/modules/memoserv/list.cpp new file mode 100644 index 000000000..8215315b0 --- /dev/null +++ b/modules/memoserv/list.cpp @@ -0,0 +1,163 @@ +/* MemoServ core functions + * + * (C) 2003-2014 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +#include "module.h" + +class CommandMSList : public Command +{ + public: + CommandMSList(Module *creator) : Command(creator, "memoserv/list", 0, 2) + { + this->SetDesc(_("List your memos")); + this->SetSyntax(_("[\037channel\037] [\037list\037 | NEW]")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override + { + + Anope::string param = !params.empty() ? params[0] : "", chan; + ChanServ::Channel *ci = NULL; + MemoServ::MemoInfo *mi; + + if (!param.empty() && param[0] == '#') + { + chan = param; + param = params.size() > 1 ? params[1] : ""; + + ci = ChanServ::Find(chan); + if (!ci) + { + source.Reply(_("Channel \002{0}\002 isn't registered."), chan); + return; + } + + if (!source.AccessFor(ci).HasPriv("MEMO")) + { + source.Reply(_("Access denied. You do not have privilege \002{0}\002 on \002{1}\002."), "MEMO", ci->GetName()); + return; + } + + mi = ci->GetMemos(); + } + else + mi = source.nc->GetMemos(); + + if (!param.empty() && !isdigit(param[0]) && !param.equals_ci("NEW")) + { + this->OnSyntaxError(source, param); + return; + } + + if (!mi) + return; + + auto memos = mi->GetMemos(); + + if (!memos.size()) + { + if (!chan.empty()) + source.Reply(_("\002{0}\002 has no memos."), chan); + else + source.Reply(_("You have no memos.")); + return; + } + + ListFormatter list(source.GetAccount()); + + list.AddColumn(_("Number")).AddColumn(_("Sender")).AddColumn(_("Date/Time")); + + if (!param.empty() && isdigit(param[0])) + { + NumberList(param, false, + [&](unsigned int number) + { + if (!number || number > memos.size()) + return; + + MemoServ::Memo *m = mi->GetMemo(number - 1); + + ListFormatter::ListEntry entry; + entry["Number"] = (m->GetUnread() ? "* " : " ") + stringify(number); + entry["Sender"] = m->GetSender(); + entry["Date/Time"] = Anope::strftime(m->GetTime(), source.GetAccount()); + list.AddEntry(entry); + }, + []{}); + } + else + { + if (!param.empty()) + { + unsigned i, end; + for (i = 0, end = memos.size(); i < end; ++i) + if (mi->GetMemo(i)->GetUnread()) + break; + if (i == end) + { + if (!chan.empty()) + source.Reply(_("\002{0}\002 has no new memos."), chan); + else + source.Reply(_("You have no new memos.")); + return; + } + } + + for (unsigned i = 0, end = memos.size(); i < end; ++i) + { + if (!param.empty() && !mi->GetMemo(i)->GetUnread()) + continue; + + MemoServ::Memo *m = mi->GetMemo(i); + + ListFormatter::ListEntry entry; + entry["Number"] = (m->GetUnread() ? "* " : " ") + stringify(i + 1); + entry["Sender"] = m->GetSender(); + entry["Date/Time"] = Anope::strftime(m->GetTime(), source.GetAccount()); + list.AddEntry(entry); + } + } + + std::vector<Anope::string> replies; + list.Process(replies); + + source.Reply(_("Memos for \002{0}\002:"), ci ? ci->GetName().c_str() : source.GetNick().c_str()); + for (unsigned i = 0; i < replies.size(); ++i) + source.Reply(replies[i]); + } + + bool OnHelp(CommandSource &source, const Anope::string &subcommand) override + { + source.Reply(_("Lists the memos you currently have." + " With \002NEW\002, lists only new (unread) memos." + " Unread memos are marked with a \"*\" to the left of the memo number." + " You can also specify a list of numbers, as in the example below:\n" + "\n" + "Example:\n" + "\n" + " {0} 2-5,7-9\n" + " Lists memos numbered 2 through 5 and 7 through 9.")); + return true; + } +}; + +class MSList : public Module +{ + CommandMSList commandmslist; + + public: + MSList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR) + , commandmslist(this) + { + + } +}; + +MODULE_INIT(MSList) diff --git a/modules/memoserv/main/CMakeLists.txt b/modules/memoserv/main/CMakeLists.txt new file mode 100644 index 000000000..781f0ef1f --- /dev/null +++ b/modules/memoserv/main/CMakeLists.txt @@ -0,0 +1 @@ +build_subdir(${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/modules/memoserv/main/ignore.cpp b/modules/memoserv/main/ignore.cpp new file mode 100644 index 000000000..e85011c00 --- /dev/null +++ b/modules/memoserv/main/ignore.cpp @@ -0,0 +1,27 @@ +#include "memo.h" +#include "ignoretype.h" + +IgnoreImpl::~IgnoreImpl() +{ +} + +MemoServ::MemoInfo *IgnoreImpl::GetMemoInfo() +{ + return Get(&IgnoreType::mi); +} + +void IgnoreImpl::SetMemoInfo(MemoServ::MemoInfo *m) +{ + Set(&IgnoreType::mi, m); +} + +Anope::string IgnoreImpl::GetMask() +{ + return Get(&IgnoreType::mask); +} + +void IgnoreImpl::SetMask(const Anope::string &mask) +{ + Set(&IgnoreType::mask, mask); |
