9
3

Chat.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. /*
  2. EQ2Emulator: Everquest II Server Emulator
  3. Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
  4. This file is part of EQ2Emulator.
  5. EQ2Emulator is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. EQ2Emulator is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "Chat.h"
  17. #include "../../common/Log.h"
  18. #include "../../common/ConfigReader.h"
  19. #include "../../common/PacketStruct.h"
  20. #include "../Rules/Rules.h"
  21. extern RuleManager rule_manager;
  22. //devn00b
  23. #ifdef DISCORD
  24. #ifndef WIN32
  25. #include <dpp/dpp.h>
  26. #include "ChatChannel.h"
  27. extern ChatChannel channel;
  28. #endif
  29. #endif
  30. extern ConfigReader configReader;
  31. Chat::Chat() {
  32. m_channels.SetName("Chat::Channels");
  33. }
  34. Chat::~Chat() {
  35. vector<ChatChannel *>::iterator itr;
  36. m_channels.writelock(__FUNCTION__, __LINE__);
  37. for (itr = channels.begin(); itr != channels.end(); itr++)
  38. safe_delete(*itr);
  39. m_channels.releasewritelock(__FUNCTION__, __LINE__);
  40. }
  41. void Chat::AddChannel(ChatChannel *channel) {
  42. m_channels.writelock(__FUNCTION__, __LINE__);
  43. channels.push_back(channel);
  44. m_channels.releasewritelock(__FUNCTION__, __LINE__);
  45. }
  46. unsigned int Chat::GetNumChannels() {
  47. unsigned int ret;
  48. m_channels.readlock(__FUNCTION__, __LINE__);
  49. ret = (unsigned int)channels.size();
  50. m_channels.releasereadlock(__FUNCTION__, __LINE__);
  51. return ret;
  52. }
  53. EQ2Packet * Chat::GetWorldChannelList(Client *client) {
  54. PacketStruct *packet_struct = configReader.getStruct("WS_AvailWorldChannels", client->GetVersion());
  55. Player *player = client->GetPlayer();
  56. vector<ChatChannel *> channels_to_send;
  57. vector<ChatChannel *>::iterator itr;
  58. ChatChannel *channel;
  59. EQ2Packet *packet;
  60. int32 i = 0;
  61. bool add;
  62. if (packet_struct == NULL) {
  63. LogWrite(CHAT__ERROR, 0, "Chat", "Could not find packet 'WS_AvailWorldChannels' for client %s on version %i\n", player->GetName(), client->GetVersion());
  64. return NULL;
  65. }
  66. m_channels.readlock(__FUNCTION__, __LINE__);
  67. for (itr = channels.begin(); itr != channels.end(); itr++) {
  68. channel = *itr;
  69. if (channel->GetType() == CHAT_CHANNEL_TYPE_WORLD) {
  70. add = true;
  71. if (add && !channel->CanJoinChannelByLevel(player->GetLevel()))
  72. add = false;
  73. if (add && !channel->CanJoinChannelByRace(player->GetRace()))
  74. add = false;
  75. if (add && !channel->CanJoinChannelByClass(player->GetAdventureClass()))
  76. add = false;
  77. if (add)
  78. channels_to_send.push_back(channel);
  79. }
  80. }
  81. m_channels.releasereadlock(__FUNCTION__, __LINE__);
  82. packet_struct->setArrayLengthByName("num_channels", channels_to_send.size());
  83. for (itr = channels_to_send.begin(); itr != channels_to_send.end(); itr++, i++) {
  84. packet_struct->setArrayDataByName("channel_name", (*itr)->GetName(), i);
  85. packet_struct->setArrayDataByName("unknown", 0, i);
  86. }
  87. packet = packet_struct->serialize();
  88. safe_delete(packet_struct);
  89. return packet;
  90. }
  91. bool Chat::ChannelExists(const char *channel_name) {
  92. vector<ChatChannel *>::iterator itr;
  93. bool ret = false;
  94. m_channels.readlock(__FUNCTION__, __LINE__);
  95. for (itr = channels.begin(); itr != channels.end(); itr++) {
  96. if (strncasecmp(channel_name, (*itr)->GetName(), CHAT_CHANNEL_MAX_NAME) == 0) {
  97. ret = true;
  98. break;
  99. }
  100. }
  101. m_channels.releasereadlock(__FUNCTION__, __LINE__);
  102. return ret;
  103. }
  104. bool Chat::HasPassword(const char *channel_name) {
  105. vector<ChatChannel *>::iterator itr;
  106. bool ret = false;
  107. m_channels.readlock(__FUNCTION__, __LINE__);
  108. for (itr = channels.begin(); itr != channels.end(); itr++) {
  109. if (strncasecmp(channel_name, (*itr)->GetName(), CHAT_CHANNEL_MAX_NAME) == 0) {
  110. ret = (*itr)->HasPassword();
  111. break;
  112. }
  113. }
  114. m_channels.releasereadlock(__FUNCTION__, __LINE__);
  115. return ret;
  116. }
  117. bool Chat::PasswordMatches(const char *channel_name, const char *password) {
  118. vector<ChatChannel *>::iterator itr;
  119. bool ret = false;
  120. m_channels.readlock(__FUNCTION__, __LINE__);
  121. for (itr = channels.begin(); itr != channels.end(); itr++) {
  122. if (strncasecmp(channel_name, (*itr)->GetName(), CHAT_CHANNEL_MAX_NAME) == 0) {
  123. ret = (*itr)->PasswordMatches(password);
  124. break;
  125. }
  126. }
  127. m_channels.releasereadlock(__FUNCTION__, __LINE__);
  128. return ret;
  129. }
  130. bool Chat::CreateChannel(const char *channel_name) {
  131. return CreateChannel(channel_name, NULL);
  132. }
  133. bool Chat::CreateChannel(const char *channel_name, const char *password) {
  134. LogWrite(CHAT__DEBUG, 0, "Chat", "Channel %s being created", channel_name);
  135. ChatChannel *channel = new ChatChannel();
  136. channel->SetName(channel_name);
  137. channel->SetType(CHAT_CHANNEL_TYPE_CUSTOM);
  138. if (password != NULL)
  139. channel->SetPassword(password);
  140. m_channels.writelock(__FUNCTION__, __LINE__);
  141. channels.push_back(channel);
  142. m_channels.releasewritelock(__FUNCTION__, __LINE__);
  143. return true;
  144. }
  145. bool Chat::IsInChannel(Client *client, const char *channel_name) {
  146. vector<ChatChannel *>::iterator itr;
  147. bool ret = false;
  148. m_channels.readlock(__FUNCTION__, __LINE__);
  149. for (itr = channels.begin(); itr != channels.end(); itr++) {
  150. if (strncasecmp(channel_name, (*itr)->GetName(), CHAT_CHANNEL_MAX_NAME) == 0) {
  151. ret = (*itr)->IsInChannel(client->GetCharacterID());
  152. break;
  153. }
  154. }
  155. m_channels.releasereadlock(__FUNCTION__, __LINE__);
  156. return ret;
  157. }
  158. bool Chat::JoinChannel(Client *client, const char *channel_name) {
  159. vector<ChatChannel *>::iterator itr;
  160. bool ret = false;
  161. LogWrite(CHAT__DEBUG, 1, "Chat", "Client %s is joining channel %s", client->GetPlayer()->GetName(), channel_name);
  162. m_channels.writelock(__FUNCTION__, __LINE__);
  163. for (itr = channels.begin(); itr != channels.end(); itr++) {
  164. if (strncasecmp(channel_name, (*itr)->GetName(), CHAT_CHANNEL_MAX_NAME) == 0) {
  165. ret = (*itr)->JoinChannel(client);
  166. break;
  167. }
  168. }
  169. m_channels.releasewritelock(__FUNCTION__, __LINE__);
  170. return ret;
  171. }
  172. bool Chat::LeaveChannel(Client *client, const char *channel_name) {
  173. vector<ChatChannel *>::iterator itr;
  174. bool ret = false;
  175. LogWrite(CHAT__DEBUG, 1, "Chat", "Client %s is leaving channel %s", client->GetPlayer()->GetName(), channel_name);
  176. m_channels.writelock(__FUNCTION__, __LINE__);
  177. for (itr = channels.begin(); itr != channels.end(); itr++) {
  178. if (strncasecmp(channel_name, (*itr)->GetName(), CHAT_CHANNEL_MAX_NAME) == 0) {
  179. ret = (*itr)->LeaveChannel(client);
  180. if ((*itr)->GetType() == CHAT_CHANNEL_TYPE_CUSTOM && (*itr)->GetNumClients() == 0) {
  181. LogWrite(CHAT__DEBUG, 0, "Chat", "Custom channel %s has 0 clients left, deleting channel", channel_name);
  182. safe_delete(*itr);
  183. channels.erase(itr);
  184. }
  185. break;
  186. }
  187. }
  188. m_channels.releasewritelock(__FUNCTION__, __LINE__);
  189. return ret;
  190. }
  191. bool Chat::LeaveAllChannels(Client *client) {
  192. vector<ChatChannel *>::iterator itr;
  193. ChatChannel *channel;
  194. bool erased;
  195. m_channels.writelock(__FUNCTION__, __LINE__);
  196. itr = channels.begin();
  197. while (itr != channels.end()) {
  198. channel = *itr;
  199. erased = false;
  200. if (channel->IsInChannel(client->GetCharacterID())) {
  201. LogWrite(CHAT__DEBUG, 1, "Chat", "Client %s is leaving channel %s", client->GetPlayer()->GetName(), channel->GetName());
  202. channel->LeaveChannel(client);
  203. if (channel->GetType() == CHAT_CHANNEL_TYPE_CUSTOM && channel->GetNumClients() == 0) {
  204. LogWrite(CHAT__DEBUG, 0, "Chat", "Custom channel %s has 0 clients left, deleting channel", channel->GetName());
  205. safe_delete(*itr);
  206. itr = channels.erase(itr);
  207. erased = true;
  208. }
  209. }
  210. if (!erased)
  211. itr++;
  212. }
  213. m_channels.releasewritelock(__FUNCTION__, __LINE__);
  214. return true;
  215. }
  216. bool Chat::TellChannel(Client *client, const char *channel_name, const char *message, const char* name) {
  217. vector<ChatChannel *>::iterator itr;
  218. bool ret = false;
  219. bool enablediscord = rule_manager.GetGlobalRule(R_Discord, DiscordEnabled)->GetBool();
  220. const char* discordchan = rule_manager.GetGlobalRule(R_Discord, DiscordChannel)->GetString();
  221. m_channels.readlock(__FUNCTION__, __LINE__);
  222. for (itr = channels.begin(); itr != channels.end(); itr++) {
  223. if (strncasecmp(channel_name, (*itr)->GetName(), CHAT_CHANNEL_MAX_NAME) == 0) {
  224. if (client && name)
  225. ret = (*itr)->TellChannelClient(client, message, name);
  226. else
  227. ret = (*itr)->TellChannel(client, message, name);
  228. if(enablediscord == true && client){
  229. if (strcmp(channel_name, discordchan) != 0){
  230. m_channels.releasereadlock(__FUNCTION__, __LINE__);
  231. return ret;
  232. }
  233. #ifdef DISCORD
  234. if (client) {
  235. std::string whofrom = client->GetPlayer()->GetName();
  236. std::string msg = string(message);
  237. ret = PushDiscordMsg(msg.c_str(), whofrom.c_str());
  238. }
  239. #endif
  240. }
  241. break;
  242. }
  243. }
  244. m_channels.releasereadlock(__FUNCTION__, __LINE__);
  245. return ret;
  246. }
  247. bool Chat::SendChannelUserList(Client *client, const char *channel_name) {
  248. vector<ChatChannel *>::iterator itr;
  249. bool ret = false;
  250. m_channels.readlock(__FUNCTION__, __LINE__);
  251. for (itr = channels.begin(); itr != channels.end(); itr++) {
  252. if (strncasecmp(channel_name, (*itr)->GetName(), CHAT_CHANNEL_MAX_NAME) == 0) {
  253. ret = (*itr)->SendChannelUserList(client);
  254. break;
  255. }
  256. }
  257. m_channels.releasereadlock(__FUNCTION__, __LINE__);
  258. return ret;
  259. }
  260. ChatChannel* Chat::GetChannel(const char *channel_name) {
  261. vector<ChatChannel *>::iterator itr;
  262. ChatChannel* ret = 0;
  263. m_channels.readlock(__FUNCTION__, __LINE__);
  264. for (itr = channels.begin(); itr != channels.end(); itr++) {
  265. if (strncasecmp(channel_name, (*itr)->GetName(), CHAT_CHANNEL_MAX_NAME) == 0) {
  266. ret = (*itr);
  267. break;
  268. }
  269. }
  270. m_channels.releasereadlock(__FUNCTION__, __LINE__);
  271. return ret;
  272. }
  273. #ifdef DISCORD
  274. //this sends chat from EQ2EMu to Discord. Currently using webhooks. Makes things simpler code wise.
  275. int Chat::PushDiscordMsg(const char* msg, const char* from) {
  276. bool enablediscord = rule_manager.GetGlobalRule(R_Discord, DiscordEnabled)->GetBool();
  277. if(enablediscord == false) {
  278. LogWrite(INIT__INFO, 0,"Discord","Bot Disabled By Rule...");
  279. return 0;
  280. }
  281. m_channels.readlock(__FUNCTION__, __LINE__);
  282. const char* hook = rule_manager.GetGlobalRule(R_Discord, DiscordWebhookURL)->GetString();
  283. std::string servername = net.GetWorldName();
  284. char ourmsg[4096];
  285. //form our message
  286. sprintf(ourmsg,"[%s] [%s] Says: %s",from, servername.c_str(), msg);
  287. /* send a message with this webhook */
  288. dpp::cluster bot("");
  289. dpp::webhook wh(hook);
  290. bot.execute_webhook(wh, dpp::message(ourmsg));
  291. m_channels.releasereadlock(__FUNCTION__, __LINE__);
  292. return 1;
  293. }
  294. #endif