1 /*
2    Copyright (C) 2017-2018 by the Battle for Wesnoth Project https://www.wesnoth.org/
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2 of the License, or
7    (at your option) any later version.
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY.
10 
11    See the COPYING file for more details.
12 */
13 
14 #include "chat_events.hpp"
15 
16 #include "formula/string_utils.hpp"
17 #include "gettext.hpp"
18 #include "log.hpp"
19 #include "map_command_handler.hpp"
20 #include "chat_command_handler.hpp"
21 #include "preferences/credentials.hpp"
22 #include "preferences/general.hpp"
23 #include "preferences/game.hpp"
24 
25 #include <boost/range/algorithm/find_if.hpp>
26 
27 static lg::log_domain log_engine("engine");
28 #define ERR_NG LOG_STREAM(err, log_engine)
29 #define LOG_NG LOG_STREAM(info, log_engine)
30 
31 namespace events {
32 
chat_handler()33 chat_handler::chat_handler()
34 {
35 }
36 
~chat_handler()37 chat_handler::~chat_handler()
38 {
39 }
40 
41 /**
42 * Change the log level of a log domain.
43 *
44 * @param data string of the form: "@<level@> @<domain@>"
45 */
change_logging(const std::string & data)46 void chat_handler::change_logging(const std::string& data) {
47 	const std::string::const_iterator j =
48 		std::find(data.begin(), data.end(), ' ');
49 	if (j == data.end()) return;
50 	const std::string level(data.begin(), j);
51 	const std::string domain(j + 1, data.end());
52 	int severity;
53 	if (level == "error") severity = lg::err().get_severity();
54 	else if (level == "warning") severity = lg::warn().get_severity();
55 	else if (level == "info") severity = lg::info().get_severity();
56 	else if (level == "debug") severity = lg::debug().get_severity();
57 	else {
58 		utils::string_map symbols;
59 		symbols["level"] = level;
60 		const std::string& msg =
61 			VGETTEXT("Unknown debug level: '$level'.", symbols);
62 		ERR_NG << msg << std::endl;
63 		add_chat_message(time(nullptr), _("error"), 0, msg);
64 		return;
65 	}
66 	if (!lg::set_log_domain_severity(domain, severity)) {
67 		utils::string_map symbols;
68 		symbols["domain"] = domain;
69 		const std::string& msg =
70 			VGETTEXT("Unknown debug domain: '$domain'.", symbols);
71 		ERR_NG << msg << std::endl;
72 		add_chat_message(time(nullptr), _("error"), 0, msg);
73 		return;
74 	}
75 	else {
76 		utils::string_map symbols;
77 		symbols["level"] = level;
78 		symbols["domain"] = domain;
79 		const std::string& msg =
80 			VGETTEXT("Switched domain: '$domain' to level: '$level'.", symbols);
81 		LOG_NG << msg << "\n";
82 		add_chat_message(time(nullptr), "log", 0, msg);
83 	}
84 }
85 
send_command(const std::string & cmd,const std::string & args)86 void chat_handler::send_command(const std::string& cmd, const std::string& args /* = "" */) {
87 	config data;
88 	if (cmd == "muteall") {
89 		data.add_child(cmd);
90 	}
91 	else if (cmd == "query") {
92 		data.add_child(cmd)["type"] = args;
93 	}
94 	else if (cmd == "ban" || cmd == "unban" || cmd == "kick"
95 		|| cmd == "mute" || cmd == "unmute") {
96 		data.add_child(cmd)["username"] = args;
97 	}
98 	else if (cmd == "ping") {
99 		data[cmd] = std::to_string(time(nullptr));
100 	}
101 	else if (cmd == "report") {
102 		data.add_child("query")["type"] = "report " + args;
103 	}
104 	else if (cmd == "join") {
105 		data.add_child("room_join")["room"] = args;
106 	}
107 	else if (cmd == "part") {
108 		data.add_child("room_part")["room"] = args;
109 	}
110 	send_to_server(data);
111 }
112 
do_speak(const std::string & message,bool allies_only)113 void chat_handler::do_speak(const std::string& message, bool allies_only)
114 {
115 	if (message.empty() || message == "/") {
116 		return;
117 	}
118 	bool is_command = (message[0] == '/');
119 	bool quoted_command = (is_command && message[1] == ' ');
120 
121 	if (!is_command) {
122 		send_chat_message(message, allies_only);
123 		return;
124 	}
125 	else if (quoted_command) {
126 		send_chat_message(std::string(message.begin() + 2, message.end()), allies_only);
127 		return;
128 	}
129 	std::string cmd(message.begin() + 1, message.end());
130 	chat_command_handler cch(*this, allies_only);
131 	cch.dispatch(cmd);
132 }
133 
user_relation_changed(const std::string &)134 void chat_handler::user_relation_changed(const std::string& /*name*/)
135 {
136 }
137 
send_whisper(const std::string & receiver,const std::string & message)138 void chat_handler::send_whisper(const std::string& receiver, const std::string& message)
139 {
140 	config cwhisper, data;
141 	cwhisper["receiver"] = receiver;
142 	cwhisper["message"] = message;
143 	cwhisper["sender"] = preferences::login();
144 	data.add_child("whisper", std::move(cwhisper));
145 	send_to_server(data);
146 }
147 
add_whisper_sent(const std::string & receiver,const std::string & message)148 void chat_handler::add_whisper_sent(const std::string& receiver, const std::string& message)
149 {
150 	utils::string_map symbols;
151 	symbols["receiver"] = receiver;
152 	add_chat_message(time(nullptr), VGETTEXT("whisper to $receiver", symbols), 0, message);
153 }
154 
add_whisper_received(const std::string & sender,const std::string & message)155 void chat_handler::add_whisper_received(const std::string& sender, const std::string& message)
156 {
157 	utils::string_map symbols;
158 	symbols["sender"] = sender;
159 	add_chat_message(time(nullptr), VGETTEXT("whisper: $sender", symbols), 0, message);
160 }
161 
send_chat_room_message(const std::string & room,const std::string & message)162 void chat_handler::send_chat_room_message(const std::string& room,
163 	const std::string& message)
164 {
165 	config cmsg, data;
166 	cmsg["room"] = room;
167 	cmsg["message"] = message;
168 	cmsg["sender"] = preferences::login();
169 	data.add_child("message", std::move(cmsg));
170 	send_to_server(data);
171 }
172 
add_chat_room_message_sent(const std::string & room,const std::string & message)173 void chat_handler::add_chat_room_message_sent(const std::string &room, const std::string &message)
174 {
175 	add_chat_room_message_received(room, preferences::login(), message);
176 }
177 
add_chat_room_message_received(const std::string & room,const std::string & speaker,const std::string & message)178 void chat_handler::add_chat_room_message_received(const std::string &room,
179 	const std::string &speaker, const std::string &message)
180 {
181 	add_chat_message(time(nullptr), room + ": " + speaker, 0, message, events::chat_handler::MESSAGE_PRIVATE);
182 }
183 
184 }
185