1 /*
2  *
3  * (C) 2003-2020 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 CommandBSSetGreet : public Command
15 {
16  public:
CommandBSSetGreet(Module * creator,const Anope::string & sname="botserv/set/greet")17 	CommandBSSetGreet(Module *creator, const Anope::string &sname = "botserv/set/greet") : Command(creator, sname, 2, 2)
18 	{
19 		this->SetDesc(_("Enable greet messages"));
20 		this->SetSyntax(_("\037channel\037 {\037ON|OFF\037}"));
21 	}
22 
Execute(CommandSource & source,const std::vector<Anope::string> & params)23 	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
24 	{
25 		ChannelInfo *ci = ChannelInfo::Find(params[0]);
26 		const Anope::string &value = params[1];
27 
28 		if (ci == NULL)
29 		{
30 			source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
31 			return;
32 		}
33 
34 		if (!source.HasPriv("botserv/administration") && !source.AccessFor(ci).HasPriv("SET"))
35 		{
36 			source.Reply(ACCESS_DENIED);
37 			return;
38 		}
39 
40 		if (Anope::ReadOnly)
41 		{
42 			source.Reply(READ_ONLY_MODE);
43 			return;
44 		}
45 
46 		if (value.equals_ci("ON"))
47 		{
48 			bool override = !source.AccessFor(ci).HasPriv("SET");
49 			Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enable greets";
50 
51 			ci->Extend<bool>("BS_GREET");
52 			source.Reply(_("Greet mode is now \002on\002 on channel %s."), ci->name.c_str());
53 		}
54 		else if (value.equals_ci("OFF"))
55 		{
56 			bool override = !source.AccessFor(ci).HasPriv("SET");
57 			Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to disable greets";
58 
59 			ci->Shrink<bool>("BS_GREET");
60 			source.Reply(_("Greet mode is now \002off\002 on channel %s."), ci->name.c_str());
61 		}
62 		else
63 			this->OnSyntaxError(source, source.command);
64 	}
65 
OnHelp(CommandSource & source,const Anope::string &)66 	bool OnHelp(CommandSource &source, const Anope::string &) anope_override
67 	{
68 		this->SendSyntax(source);
69 		source.Reply(_(" \n"
70 			"Enables or disables \002greet\002 mode on a channel.\n"
71 			"When it is enabled, the bot will display greet\n"
72 			"messages of users joining the channel, provided\n"
73 			"they have enough access to the channel."));
74 			return true;
75 	}
76 };
77 
78 class CommandNSSetGreet : public Command
79 {
80  public:
CommandNSSetGreet(Module * creator,const Anope::string & sname="nickserv/set/greet",size_t min=0)81 	CommandNSSetGreet(Module *creator, const Anope::string &sname = "nickserv/set/greet", size_t min = 0) : Command(creator, sname, min, min + 1)
82 	{
83 		this->SetDesc(_("Associate a greet message with your nickname"));
84 		this->SetSyntax(_("\037message\037"));
85 	}
86 
Run(CommandSource & source,const Anope::string & user,const Anope::string & param)87 	void Run(CommandSource &source, const Anope::string &user, const Anope::string &param)
88 	{
89 		if (Anope::ReadOnly)
90 		{
91 			source.Reply(READ_ONLY_MODE);
92 			return;
93 		}
94 
95 		const NickAlias *na = NickAlias::Find(user);
96 		if (!na)
97 		{
98 			source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
99 			return;
100 		}
101 		NickCore *nc = na->nc;
102 
103 		EventReturn MOD_RESULT;
104 		FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
105 		if (MOD_RESULT == EVENT_STOP)
106 			return;
107 
108 		if (!param.empty())
109 		{
110 			Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change the greet of " << nc->display;
111 			nc->Extend<Anope::string>("greet", param);
112 			source.Reply(_("Greet message for \002%s\002 changed to \002%s\002."), nc->display.c_str(), param.c_str());
113 		}
114 		else
115 		{
116 			Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to unset the greet of " << nc->display;
117 			nc->Shrink<Anope::string>("greet");
118 			source.Reply(_("Greet message for \002%s\002 unset."), nc->display.c_str());
119 		}
120 	}
121 
Execute(CommandSource & source,const std::vector<Anope::string> & params)122 	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
123 	{
124 		this->Run(source, source.nc->display, params.size() > 0 ? params[0] : "");
125 	}
126 
OnHelp(CommandSource & source,const Anope::string &)127 	bool OnHelp(CommandSource &source, const Anope::string &) anope_override
128 	{
129 		this->SendSyntax(source);
130 		source.Reply(" ");
131 		source.Reply(_("Makes the given message the greet of your nickname, that\n"
132 				"will be displayed when joining a channel that has GREET\n"
133 				"option enabled, provided that you have the necessary\n"
134 				"access on it."));
135 		return true;
136 	}
137 };
138 
139 class CommandNSSASetGreet : public CommandNSSetGreet
140 {
141  public:
CommandNSSASetGreet(Module * creator)142 	CommandNSSASetGreet(Module *creator) : CommandNSSetGreet(creator, "nickserv/saset/greet", 1)
143 	{
144 		this->ClearSyntax();
145 		this->SetSyntax(_("\037nickname\037 \037message\037"));
146 	}
147 
Execute(CommandSource & source,const std::vector<Anope::string> & params)148 	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
149 	{
150 		this->Run(source, params[0], params.size() > 1 ? params[1] : "");
151 	}
152 
OnHelp(CommandSource & source,const Anope::string &)153 	bool OnHelp(CommandSource &source, const Anope::string &) anope_override
154 	{
155 		this->SendSyntax(source);
156 		source.Reply(" ");
157 		source.Reply(_("Makes the given message the greet of the nickname, that\n"
158 				"will be displayed when joining a channel that has GREET\n"
159 				"option enabled, provided that the user has the necessary\n"
160 				"access on it."));
161 		return true;
162 	}
163 };
164 
165 class Greet : public Module
166 {
167 	/* channel setting for whether or not greet should be shown */
168 	SerializableExtensibleItem<bool> bs_greet;
169 	/* user greets */
170 	SerializableExtensibleItem<Anope::string> ns_greet;
171 
172 	CommandBSSetGreet commandbssetgreet;
173 	CommandNSSetGreet commandnssetgreet;
174 	CommandNSSASetGreet commandnssasetgreet;
175 
176  public:
Greet(const Anope::string & modname,const Anope::string & creator)177 	Greet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
178 		bs_greet(this, "BS_GREET"),
179 		ns_greet(this, "greet"),
180 		commandbssetgreet(this),
181 		commandnssetgreet(this), commandnssasetgreet(this)
182 	{
183 	}
184 
OnJoinChannel(User * user,Channel * c)185 	void OnJoinChannel(User *user, Channel *c) anope_override
186 	{
187 		/* Only display the greet if the main uplink we're connected
188 		 * to has synced, or we'll get greet-floods when the net
189 		 * recovers from a netsplit. -GD
190 		 */
191 		if (!c->ci || !c->ci->bi || !user->server->IsSynced() || !user->Account())
192 			return;
193 
194 		Anope::string *greet = ns_greet.Get(user->Account());
195 		if (bs_greet.HasExt(c->ci) && greet != NULL && !greet->empty() && c->FindUser(c->ci->bi) && c->ci->AccessFor(user).HasPriv("GREET"))
196 		{
197 			IRCD->SendPrivmsg(*c->ci->bi, c->name, "[%s] %s", user->Account()->display.c_str(), greet->c_str());
198 			c->ci->bi->lastmsg = Anope::CurTime;
199 		}
200 	}
201 
OnNickInfo(CommandSource & source,NickAlias * na,InfoFormatter & info,bool show_hidden)202 	void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) anope_override
203 	{
204 		Anope::string *greet = ns_greet.Get(na->nc);
205 		if (greet != NULL)
206 			info[_("Greet")] = *greet;
207 	}
208 
OnBotInfo(CommandSource & source,BotInfo * bi,ChannelInfo * ci,InfoFormatter & info)209 	void OnBotInfo(CommandSource &source, BotInfo *bi, ChannelInfo *ci, InfoFormatter &info) anope_override
210 	{
211 		if (bs_greet.HasExt(ci))
212 			info.AddOption(_("Greet"));
213 	}
214 };
215 
216 MODULE_INIT(Greet)
217