00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "module.h"
00015 #include "memoserv.h"
00016
00017 static bool SendMemoMail(NickCore *nc, MemoInfo *mi, Memo *m)
00018 {
00019 Anope::string subject = translate(nc, Config->MailMemoSubject.c_str());
00020 Anope::string message = translate(nc, Config->MailMemoMessage.c_str());
00021
00022 subject = subject.replace_all_cs("%n", nc->display);
00023 subject = subject.replace_all_cs("%s", m->sender);
00024 subject = subject.replace_all_cs("%d", mi->GetIndex(m));
00025 subject = subject.replace_all_cs("%t", m->text);
00026
00027 message = message.replace_all_cs("%n", nc->display);
00028 message = message.replace_all_cs("%s", m->sender);
00029 message = message.replace_all_cs("%d", mi->GetIndex(m));
00030 message = message.replace_all_cs("%t", m->text);
00031
00032 return Mail(nc, subject, message);
00033 }
00034
00035 class MyMemoServService : public MemoServService
00036 {
00037 public:
00038 MyMemoServService(Module *m) : MemoServService(m) { }
00039
00040 MemoInfo *GetMemoInfo(const Anope::string &target, bool &ischan) anope_override
00041 {
00042 if (!target.empty() && target[0] == '#')
00043 {
00044 ischan = true;
00045 ChannelInfo *ci = cs_findchan(target);
00046 if (ci != NULL)
00047 return &ci->memos;
00048 }
00049 else
00050 {
00051 ischan = false;
00052 NickAlias *na = findnick(target);
00053 if (na != NULL)
00054 return &na->nc->memos;
00055 }
00056
00057 return NULL;
00058 }
00059
00060 MemoResult Send(const Anope::string &source, const Anope::string &target, const Anope::string &message, bool force) anope_override
00061 {
00062 bool ischan;
00063 MemoInfo *mi = this->GetMemoInfo(target, ischan);
00064
00065 if (mi == NULL)
00066 return MEMO_INVALID_TARGET;
00067
00068 User *sender = finduser(source);
00069 if (sender != NULL && !sender->HasPriv("memoserv/no-limit") && !force)
00070 {
00071 if (Config->MSSendDelay > 0 && sender->lastmemosend + Config->MSSendDelay > Anope::CurTime)
00072 return MEMO_TOO_FAST;
00073 else if (!mi->memomax)
00074 return MEMO_TARGET_FULL;
00075 else if (mi->memomax > 0 && mi->memos->size() >= static_cast<unsigned>(mi->memomax))
00076 return MEMO_TARGET_FULL;
00077 else if (mi->HasIgnore(sender))
00078 return MEMO_SUCCESS;
00079 }
00080
00081 if (sender != NULL)
00082 sender->lastmemosend = Anope::CurTime;
00083
00084 Memo *m = new Memo();
00085 mi->memos->push_back(m);
00086 m->owner = target;
00087 m->sender = source;
00088 m->time = Anope::CurTime;
00089 m->text = message;
00090 m->SetFlag(MF_UNREAD);
00091
00092 FOREACH_MOD(I_OnMemoSend, OnMemoSend(source, target, mi, m));
00093
00094 if (ischan)
00095 {
00096 ChannelInfo *ci = cs_findchan(target);
00097
00098 if (ci->c)
00099 {
00100 for (CUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it)
00101 {
00102 UserContainer *cu = *it;
00103
00104 if (ci->AccessFor(cu->user).HasPriv("MEMO"))
00105 {
00106 if (cu->user->Account() && cu->user->Account()->HasFlag(NI_MEMO_RECEIVE))
00107 cu->user->SendMessage(findbot(Config->MemoServ), MEMO_NEW_X_MEMO_ARRIVED, ci->name.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->MemoServ.c_str(), ci->name.c_str(), mi->memos->size());
00108 }
00109 }
00110 }
00111 }
00112 else
00113 {
00114 NickCore *nc = findnick(target)->nc;
00115
00116 if (nc->HasFlag(NI_MEMO_RECEIVE))
00117 {
00118 for (std::list<serialize_obj<NickAlias> >::const_iterator it = nc->aliases.begin(), it_end = nc->aliases.end(); it != it_end;)
00119 {
00120 const NickAlias *na = *it++;
00121 if (!na)
00122 continue;
00123 User *user = finduser(na->nick);
00124 if (user && user->IsIdentified())
00125 user->SendMessage(findbot(Config->MemoServ), MEMO_NEW_MEMO_ARRIVED, source.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->MemoServ.c_str(), mi->memos->size());
00126 }
00127 }
00128
00129
00130 if (nc->HasFlag(NI_MEMO_MAIL))
00131 SendMemoMail(nc, mi, m);
00132 }
00133
00134 return MEMO_SUCCESS;
00135 }
00136
00137 void Check(User *u)
00138 {
00139 const NickCore *nc = u->Account();
00140 if (!nc)
00141 return;
00142 const BotInfo *ms = findbot(Config->MemoServ);
00143
00144 unsigned i = 0, end = nc->memos.memos->size(), newcnt = 0;
00145 for (; i < end; ++i)
00146 if (nc->memos.GetMemo(i)->HasFlag(MF_UNREAD))
00147 ++newcnt;
00148 if (newcnt > 0)
00149 u->SendMessage(ms, newcnt == 1 ? _("You have 1 new memo.") : _("You have %d new memos."), newcnt);
00150 if (nc->memos.memomax > 0 && nc->memos.memos->size() >= static_cast<unsigned>(nc->memos.memomax))
00151 {
00152 if (nc->memos.memos->size() > static_cast<unsigned>(nc->memos.memomax))
00153 u->SendMessage(ms, _("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);
00154 else
00155 u->SendMessage(ms, _("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);
00156 }
00157 }
00158 };
00159
00160 class MemoServCore : public Module
00161 {
00162 MyMemoServService mymemoserv;
00163 public:
00164 MemoServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE),
00165 mymemoserv(this)
00166 {
00167 this->SetAuthor("Anope");
00168
00169 if (!findbot(Config->MemoServ))
00170 throw ModuleException("No bot named " + Config->MemoServ);
00171
00172 Implementation i[] = { I_OnNickIdentify, I_OnJoinChannel, I_OnUserAway, I_OnNickUpdate, I_OnPreHelp, I_OnPostHelp };
00173 ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
00174 }
00175
00176 void OnNickIdentify(User *u) anope_override
00177 {
00178 this->mymemoserv.Check(u);
00179 }
00180
00181 void OnJoinChannel(User *u, Channel *c) anope_override
00182 {
00183 if (c->ci && c->ci->AccessFor(u).HasPriv("MEMO") && c->ci->memos.memos->size() > 0)
00184 {
00185 if (c->ci->memos.memos->size() == 1)
00186 u->SendMessage(findbot(Config->MemoServ), _("There is \002%d\002 memo on channel %s."), c->ci->memos.memos->size(), c->ci->name.c_str());
00187 else
00188 u->SendMessage(findbot(Config->MemoServ), _("There are \002%d\002 memos on channel %s."), c->ci->memos.memos->size(), c->ci->name.c_str());
00189 }
00190 }
00191
00192 void OnUserAway(User *u, const Anope::string &message) anope_override
00193 {
00194 if (message.empty())
00195 this->mymemoserv.Check(u);
00196 }
00197
00198 void OnNickUpdate(User *u) anope_override
00199 {
00200 this->mymemoserv.Check(u);
00201 }
00202
00203 EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00204 {
00205 if (!params.empty() || source.c || source.service->nick != Config->MemoServ)
00206 return EVENT_CONTINUE;
00207 source.Reply(_("\002%s\002 is a utility allowing IRC users to send short\n"
00208 "messages to other IRC users, whether they are online at\n"
00209 "the time or not, or to channels(*). Both the sender's\n"
00210 "nickname and the target nickname or channel must be\n"
00211 "registered in order to send a memo.\n"
00212 "%s's commands include:"), Config->MemoServ.c_str(), Config->MemoServ.c_str());
00213 return EVENT_CONTINUE;
00214 }
00215
00216 void OnPostHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00217 {
00218 if (!params.empty() || source.c || source.service->nick != Config->MemoServ)
00219 return;
00220 source.Reply(_(" \n"
00221 "Type \002%s%s HELP \037command\037\002 for help on any of the\n"
00222 "above commands.\n"
00223 "(*) By default, any user with at least level 10 access on a\n"
00224 " channel can read that channel's memos. This can be\n"
00225 " changed with the %s \002LEVELS\002 command."), Config->UseStrictPrivMsgString.c_str(), Config->MemoServ.c_str(), Config->ChanServ.c_str());
00226 }
00227 };
00228
00229 MODULE_INIT(MemoServCore)
00230