diff options
Diffstat (limited to 'modules/memoserv/main')
| -rw-r--r-- | modules/memoserv/main/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | modules/memoserv/main/ignore.cpp | 27 | ||||
| -rw-r--r-- | modules/memoserv/main/ignore.h | 15 | ||||
| -rw-r--r-- | modules/memoserv/main/ignoretype.cpp | 10 | ||||
| -rw-r--r-- | modules/memoserv/main/ignoretype.h | 10 | ||||
| -rw-r--r-- | modules/memoserv/main/memo.cpp | 72 | ||||
| -rw-r--r-- | modules/memoserv/main/memo.h | 29 | ||||
| -rw-r--r-- | modules/memoserv/main/memoinfo.cpp | 63 | ||||
| -rw-r--r-- | modules/memoserv/main/memoinfo.h | 23 | ||||
| -rw-r--r-- | modules/memoserv/main/memoinfotype.cpp | 10 | ||||
| -rw-r--r-- | modules/memoserv/main/memoinfotype.h | 10 | ||||
| -rw-r--r-- | modules/memoserv/main/memoserv.cpp | 298 | ||||
| -rw-r--r-- | modules/memoserv/main/memotype.cpp | 14 | ||||
| -rw-r--r-- | modules/memoserv/main/memotype.h | 13 |
14 files changed, 595 insertions, 0 deletions
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); +} + diff --git a/modules/memoserv/main/ignore.h b/modules/memoserv/main/ignore.h new file mode 100644 index 000000000..c98b44adf --- /dev/null +++ b/modules/memoserv/main/ignore.h @@ -0,0 +1,15 @@ +#include "modules/memoserv.h" + +class IgnoreImpl : public MemoServ::Ignore +{ + public: + IgnoreImpl(Serialize::TypeBase *type) : MemoServ::Ignore(type) { } + IgnoreImpl(Serialize::TypeBase *type, Serialize::ID id) : MemoServ::Ignore(type, id) { } + ~IgnoreImpl(); + + MemoServ::MemoInfo *GetMemoInfo() override; + void SetMemoInfo(MemoServ::MemoInfo *) override; + + Anope::string GetMask() override; + void SetMask(const Anope::string &mask) override; +}; diff --git a/modules/memoserv/main/ignoretype.cpp b/modules/memoserv/main/ignoretype.cpp new file mode 100644 index 000000000..375f83272 --- /dev/null +++ b/modules/memoserv/main/ignoretype.cpp @@ -0,0 +1,10 @@ +#include "module.h" +#include "ignoretype.h" + +IgnoreType::IgnoreType(Module *me) : Serialize::Type<IgnoreImpl>(me, "MemoIgnore") + , mi(this, "mi", true) + , mask(this, "mask") +{ + +} + diff --git a/modules/memoserv/main/ignoretype.h b/modules/memoserv/main/ignoretype.h new file mode 100644 index 000000000..5c656f9b8 --- /dev/null +++ b/modules/memoserv/main/ignoretype.h @@ -0,0 +1,10 @@ +#include "ignore.h" + +class IgnoreType : public Serialize::Type<IgnoreImpl> +{ + public: + Serialize::ObjectField<IgnoreImpl, MemoServ::MemoInfo *> mi; + Serialize::Field<IgnoreImpl, Anope::string> mask; + + IgnoreType(Module *); +}; diff --git a/modules/memoserv/main/memo.cpp b/modules/memoserv/main/memo.cpp new file mode 100644 index 000000000..bfae64284 --- /dev/null +++ b/modules/memoserv/main/memo.cpp @@ -0,0 +1,72 @@ +//#include "memo.h" +#include "memotype.h" + +/*MemoImpl::MemoImpl() +{ + //unread = receipt = false; +}*/ + +MemoImpl::~MemoImpl() +{ +} + +MemoServ::MemoInfo *MemoImpl::GetMemoInfo() +{ + return Get(&MemoType::mi); +} + +void MemoImpl::SetMemoInfo(MemoServ::MemoInfo *mi) +{ + Set(&MemoType::mi, mi); +} + +time_t MemoImpl::GetTime() +{ + return Get(&MemoType::time); +} + +void MemoImpl::SetTime(const time_t &t) +{ + Set(&MemoType::time, t); +} + +Anope::string MemoImpl::GetSender() +{ + return Get(&MemoType::sender); +} + +void MemoImpl::SetSender(const Anope::string &s) +{ + Set(&MemoType::sender, s); +} + +Anope::string MemoImpl::GetText() +{ + return Get(&MemoType::text); +} + +void MemoImpl::SetText(const Anope::string &t) +{ + Set(&MemoType::text, t); +} + +bool MemoImpl::GetUnread() +{ + return Get(&MemoType::unread); +} + +void MemoImpl::SetUnread(const bool &b) +{ + Set(&MemoType::unread, b); +} + +bool MemoImpl::GetReceipt() +{ + return Get(&MemoType::receipt); +} + +void MemoImpl::SetReceipt(const bool &b) +{ + Set(&MemoType::receipt, b); +} + diff --git a/modules/memoserv/main/memo.h b/modules/memoserv/main/memo.h new file mode 100644 index 000000000..1a230c1e9 --- /dev/null +++ b/modules/memoserv/main/memo.h @@ -0,0 +1,29 @@ +#include "modules/memoserv.h" + +class MemoImpl : public MemoServ::Memo +{ + public: + MemoImpl(Serialize::TypeBase *type) : MemoServ::Memo(type) { } + MemoImpl(Serialize::TypeBase *type, Serialize::ID id) : MemoServ::Memo(type, id) { } + //using MemoServ::Memo::Memo; +// MemoImpl(); + ~MemoImpl(); + + MemoServ::MemoInfo *GetMemoInfo() override; + void SetMemoInfo(MemoServ::MemoInfo *) override; + + time_t GetTime() override; + void SetTime(const time_t &) override; + + Anope::string GetSender() override; + void SetSender(const Anope::string &) override; + + Anope::string GetText() override; + void SetText(const Anope::string &) override; + + bool GetUnread() override; + void SetUnread(const bool &) override; + + bool GetReceipt() override; + void SetReceipt(const bool &) override; +}; diff --git a/modules/memoserv/main/memoinfo.cpp b/modules/memoserv/main/memoinfo.cpp new file mode 100644 index 000000000..45d95533e --- /dev/null +++ b/modules/memoserv/main/memoinfo.cpp @@ -0,0 +1,63 @@ +#include "memoinfotype.h" + +MemoServ::Memo *MemoInfoImpl::GetMemo(unsigned index) +{ + auto memos = GetMemos(); + return index >= memos.size() ? nullptr : memos[index]; +} + +unsigned MemoInfoImpl::GetIndex(MemoServ::Memo *m) +{ + auto memos = GetMemos(); + for (unsigned i = 0; i < memos.size(); ++i) + if (this->GetMemo(i) == m) + return i; + return -1; // XXX wtf? +} + +void MemoInfoImpl::Del(unsigned index) +{ + delete GetMemo(index); +} + +bool MemoInfoImpl::HasIgnore(User *u) +{ + for (MemoServ::Ignore *ign : GetIgnores()) + { + const Anope::string &mask = ign->GetMask(); + if (u->nick.equals_ci(mask) || (u->Account() && u->Account()->GetDisplay().equals_ci(mask)) || Anope::Match(u->GetMask(), mask)) + return true; + } + return false; +} + +Serialize::Object *MemoInfoImpl::GetOwner() +{ + return Get(&MemoInfoType::owner); +} + +void MemoInfoImpl::SetOwner(Serialize::Object *o) +{ + Set(&MemoInfoType::owner, o); +} + +int16_t MemoInfoImpl::GetMemoMax() +{ + return Get(&MemoInfoType::memomax); +} + +void MemoInfoImpl::SetMemoMax(const int16_t &i) +{ + Set(&MemoInfoType::memomax, i); +} + +std::vector<MemoServ::Memo *> MemoInfoImpl::GetMemos() +{ + return GetRefs<MemoServ::Memo *>(MemoServ::memo); +} + +std::vector<MemoServ::Ignore *> MemoInfoImpl::GetIgnores() +{ + return GetRefs<MemoServ::Ignore *>(MemoServ::ignore); +} + diff --git a/modules/memoserv/main/memoinfo.h b/modules/memoserv/main/memoinfo.h new file mode 100644 index 000000000..22ea0734f --- /dev/null +++ b/modules/memoserv/main/memoinfo.h @@ -0,0 +1,23 @@ +#include "modules/memoserv.h" + +class MemoInfoImpl : public MemoServ::MemoInfo +{ + public: + MemoInfoImpl(Serialize::TypeBase *type) : MemoServ::MemoInfo(type) { } + MemoInfoImpl(Serialize::TypeBase *type, Serialize::ID id) : MemoServ::MemoInfo(type, id) { } + + MemoServ::Memo *GetMemo(unsigned index) override; + unsigned GetIndex(MemoServ::Memo *m) override; + void Del(unsigned index) override; + bool HasIgnore(User *u) override; + + Serialize::Object *GetOwner() override; + void SetOwner(Serialize::Object *) override; + + int16_t GetMemoMax() override; + void SetMemoMax(const int16_t &) override; + + std::vector<MemoServ::Memo *> GetMemos() override; + std::vector<MemoServ::Ignore *> GetIgnores() override; +}; + diff --git a/modules/memoserv/main/memoinfotype.cpp b/modules/memoserv/main/memoinfotype.cpp new file mode 100644 index 000000000..7eb3af72c --- /dev/null +++ b/modules/memoserv/main/memoinfotype.cpp @@ -0,0 +1,10 @@ +#include "module.h" +#include "memoinfotype.h" + +MemoInfoType::MemoInfoType(Module *me) : Serialize::Type<MemoInfoImpl>(me, "MemoInfo") + , owner(this, "owner", true) + , memomax(this, "memomax") +{ + +} + diff --git a/modules/memoserv/main/memoinfotype.h b/modules/memoserv/main/memoinfotype.h new file mode 100644 index 000000000..724a898b5 --- /dev/null +++ b/modules/memoserv/main/memoinfotype.h @@ -0,0 +1,10 @@ +#include "memoinfo.h" + +class MemoInfoType : public Serialize::Type<MemoInfoImpl> +{ + public: + Serialize::ObjectField<MemoInfoImpl, Serialize::Object *> owner; + Serialize::Field<MemoInfoImpl, int16_t> memomax; + + MemoInfoType(Module *); +}; diff --git a/modules/memoserv/main/memoserv.cpp b/modules/memoserv/main/memoserv.cpp new file mode 100644 index 000000000..a52ee746c --- /dev/null +++ b/modules/memoserv/main/memoserv.cpp @@ -0,0 +1,298 @@ +/* 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/ns_update.h" +#include "modules/help.h" +#include "modules/bs_bot.h" +#include "modules/memoserv.h" +//#include "memoinfo.h" +//#include "memo.h" +//#include "ignore.h" +#include "memotype.h" +#include "memoinfotype.h" +#include "ignoretype.h" + +class MemoServCore : public Module, public MemoServ::MemoServService + , public EventHook<Event::NickCoreCreate> + , public EventHook<Event::CreateChan> + , public EventHook<Event::BotDelete> + , public EventHook<Event::NickIdentify> + , public EventHook<Event::JoinChannel> + , public EventHook<Event::UserAway> + , public EventHook<Event::NickUpdate> + , public EventHook<Event::Help> +{ + Reference<ServiceBot> MemoServ; + EventHandlers<MemoServ::Event::MemoSend> onmemosend; + EventHandlers<MemoServ::Event::MemoDel> onmemodel; + + MemoInfoType memoinfo_type; + MemoType memo_type; + IgnoreType ignore_type; + + bool SendMemoMail(NickServ::Account *nc, MemoServ::MemoInfo *mi, MemoServ::Memo *m) + { + Anope::string subject = Language::Translate(nc, Config->GetBlock("mail")->Get<Anope::string>("memo_subject").c_str()), + message = Language::Translate(Config->GetBlock("mail")->Get<Anope::string>("memo_message").c_str()); + + subject = subject.replace_all_cs("%n", nc->GetDisplay()); + subject = subject.replace_all_cs("%s", m->GetSender()); + subject = subject.replace_all_cs("%d", stringify(mi->GetIndex(m) + 1)); + subject = subject.replace_all_cs("%t", m->GetText()); + subject = subject.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<Anope::string>("networkname")); + + message = message.replace_all_cs("%n", nc->GetDisplay()); + message = message.replace_all_cs("%s", m->GetSender()); + message = message.replace_all_cs("%d", stringify(mi->GetIndex(m) + 1)); + message = message.replace_all_cs("%t", m->GetText()); + message = message.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<Anope::string>("networkname")); + + return Mail::Send(nc, subject, message); + } + + public: + MemoServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR) + , MemoServ::MemoServService(this) + , onmemosend(this) + , onmemodel(this) + , memoinfo_type(this) + , memo_type(this) + , ignore_type(this) + { + } + + MemoResult Send(const Anope::string &source, const Anope::string &target, const Anope::string &message, bool force) override + { + bool ischan, isregistered; + MemoServ::MemoInfo *mi = GetMemoInfo(target, ischan, isregistered, true); + + if (mi == NULL) + return MEMO_INVALID_TARGET; + + User *sender = User::Find(source); + if (sender != NULL && !sender->HasPriv("memoserv/no-limit") && !force) + { + time_t send_delay = Config->GetModule("memoserv")->Get<time_t>("senddelay"); + if (send_delay > 0 && sender->lastmemosend + send_delay > Anope::CurTime) + return MEMO_TOO_FAST; + else if (!mi->GetMemoMax()) + return MEMO_TARGET_FULL; + else if (mi->GetMemoMax() > 0 && mi->GetMemos().size() >= static_cast<unsigned>(mi->GetMemoMax())) + return MEMO_TARGET_FULL; + else if (mi->HasIgnore(sender)) + return MEMO_SUCCESS; + } + + if (sender != NULL) + sender->lastmemosend = Anope::CurTime; + + MemoServ::Memo *m = new MemoImpl(&memo_type); + m->SetMemoInfo(mi); + m->SetSender(source); + m->SetTime(Anope::CurTime); + m->SetText(message); + m->SetUnread(true); + + this->onmemosend(&MemoServ::Event::MemoSend::OnMemoSend, source, target, mi, m); + + if (ischan) + { + ChanServ::Channel *ci = ChanServ::Find(target); + + if (ci->c) + { + for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it) + { + ChanUserContainer *cu = it->second; + + if (ci->AccessFor(cu->user).HasPriv("MEMO")) + { + if (cu->user->Account() && cu->user->Account()->HasFieldS("MEMO_RECEIVE")) + cu->user->SendMessage(*MemoServ, _("There is a new memo on channel \002{0}\002. Type \002{1}{2} READ {3} {4}\002 to read it."), ci->GetName(), Config->StrictPrivmsg, MemoServ->nick, ci->GetName(), mi->GetMemos().size()); // XXX + } + } + } + } + else + { + NickServ::Account *nc = NickServ::FindNick(target)->GetAccount(); + + if (nc->HasFieldS("MEMO_RECEIVE")) + for (User *u : nc->users) + u->SendMessage(*MemoServ, _("You have a new memo from \002{0}\002. Type \002{1}{2} READ {3}\002 to read it."), source, Config->StrictPrivmsg, MemoServ->nick, mi->GetMemos().size());//XXX + + /* let's get out the mail if set in the nickcore - certus */ + if (nc->HasFieldS("MEMO_MAIL")) + SendMemoMail(nc, mi, m); + } + + return MEMO_SUCCESS; + } + + void Check(User *u) override + { + NickServ::Account *nc = u->Account(); + if (!nc || !nc->GetMemos()) + return; + + auto memos = nc->GetMemos()->GetMemos(); + unsigned i = 0, end = memos.size(), newcnt = 0; + for (; i < end; ++i) + if (memos[i]->GetUnread()) + ++newcnt; + if (newcnt > 0) + u->SendMessage(*MemoServ, newcnt == 1 ? _("You have 1 new memo.") : _("You have %d new memos."), newcnt); + if (nc->GetMemos()->GetMemoMax() > 0 && memos.size() >= static_cast<unsigned>(nc->GetMemos()->GetMemoMax())) + { + if (memos.size() > static_cast<unsigned>(nc->GetMemos()->GetMemoMax())) + 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->GetMemos()->GetMemoMax()); + else + 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->GetMemos()->GetMemoMax()); + } + } + + MemoServ::Memo *CreateMemo() override + { + return new MemoImpl(&memo_type); + } + + MemoServ::Ignore *CreateIgnore() override + { + return new IgnoreImpl(&ignore_type); + } + + MemoServ::MemoInfo *GetMemoInfo(const Anope::string &target, bool &is_registered, bool &ischan, bool create) override + { + if (!target.empty() && target[0] == '#') + { + ischan = true; + ChanServ::Channel *ci = ChanServ::Find(target); + if (ci != NULL) + { + is_registered = true; + if (create && !ci->GetMemos()) + { + MemoServ::MemoInfo *mi = new MemoInfoImpl(&memoinfo_type); + mi->SetOwner(ci); + } + return ci->GetMemos(); + } + else + is_registered = false; + } + else + { + ischan = false; + NickServ::Nick *na = NickServ::FindNick(target); + if (na != NULL) + { + is_registered = true; + if (create && !na->GetAccount()->GetMemos()) + { + MemoServ::MemoInfo *mi = new MemoInfoImpl(&memoinfo_type); + mi->SetOwner(na->GetAccount()); + } + return na->GetAccount()->GetMemos(); + } + else + is_registered = false; + } + + return NULL; + } + + void OnReload(Configuration::Conf *conf) override + { + const Anope::string &msnick = conf->GetModule(this)->Get<Anope::string>("client"); + + if (msnick.empty()) + throw ConfigException(Module::name + ": <client> must be defined"); + + ServiceBot *bi = ServiceBot::Find(msnick, true); + if (!bi) + throw ConfigException(Module::name + ": no bot named " + msnick); + + MemoServ = bi; + } + + void OnNickCoreCreate(NickServ::Account *nc) override + { + MemoServ::MemoInfo *mi = new MemoInfoImpl(&memoinfo_type); + mi->SetOwner(mi); + mi->SetMemoMax(Config->GetModule(this)->Get<int>("maxmemos")); + } + + void OnCreateChan(ChanServ::Channel *ci) override + { + MemoServ::MemoInfo *mi = new MemoInfoImpl(&memoinfo_type); + mi->SetOwner(ci); + mi->SetMemoMax(Config->GetModule(this)->Get<int>("maxmemos")); + } + + void OnBotDelete(ServiceBot *bi) override + { + if (bi == MemoServ) + MemoServ = NULL; + } + + void OnNickIdentify(User *u) override + { + this->Check(u); + } + + void OnJoinChannel(User *u, Channel *c) override + { + if (u->server && u->server->IsSynced() && c->ci && c->ci->GetMemos() && !c->ci->GetMemos()->GetMemos().empty() && c->ci->AccessFor(u).HasPriv("MEMO")) + { + if (c->ci->GetMemos()->GetMemos().size() == 1) + u->SendMessage(*MemoServ, _("There is \002{0}\002 memo on channel \002{1}\002."), c->ci->GetMemos()->GetMemos().size(), c->ci->GetName()); + else + u->SendMessage(*MemoServ, _("There are \002{0}\002 memos on channel \002{1}\002."), c->ci->GetMemos()->GetMemos().size(), c->ci->GetName()); + } + } + + void OnUserAway(User *u, const Anope::string &message) override + { + if (message.empty()) + this->Check(u); + } + + void OnNickUpdate(User *u) override + { + this->Check(u); + } + + EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) override + { + if (!params.empty() || source.c || source.service != *MemoServ) + return EVENT_CONTINUE; + source.Reply(_("\002%s\002 is a utility allowing IRC users to send short\n" + "messages to other IRC users, whether they are online at\n" + "the time or not, or to channels(*). Both the sender's\n" + "nickname and the target nickname or channel must be\n" + "registered in order to send a memo.\n" + "%s's commands include:"), MemoServ->nick.c_str(), MemoServ->nick.c_str()); + return EVENT_CONTINUE; + } + + void OnPostHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) override + { + if (!params.empty() || source.c || source.service != *MemoServ) + return; + source.Reply(_(" \n" + "Type \002%s%s HELP \037command\037\002 for help on any of the\n" + "above commands."), Config->StrictPrivmsg.c_str(), MemoServ->nick.c_str()); + } +}; + +MODULE_INIT(MemoServCore) + diff --git a/modules/memoserv/main/memotype.cpp b/modules/memoserv/main/memotype.cpp new file mode 100644 index 000000000..c9144bbaa --- /dev/null +++ b/modules/memoserv/main/memotype.cpp @@ -0,0 +1,14 @@ +#include "module.h" +#include "memotype.h" + +MemoType::MemoType(Module *me) : Serialize::Type<MemoImpl>(me, "Memo") + , mi(this, "mi", true) + , time(this, "time") + , sender(this, "sender") + , text(this, "text") + , unread(this, "unread") + , receipt(this, "receipt") +{ + +} + diff --git a/modules/memoserv/main/memotype.h b/modules/memoserv/main/memotype.h new file mode 100644 index 000000000..16ac6f082 --- /dev/null +++ b/modules/memoserv/main/memotype.h @@ -0,0 +1,13 @@ +#include "memo.h" + +class MemoType : public Serialize::Type<MemoImpl> +{ + public: + Serialize::ObjectField<MemoImpl, MemoServ::MemoInfo *> mi; + Serialize::Field<MemoImpl, time_t> time; + Serialize::Field<MemoImpl, Anope::string> sender; + Serialize::Field<MemoImpl, Anope::string> text; + Serialize::Field<MemoImpl, bool> unread, receipt; + + MemoType(Module *); +}; |
