Client.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. #include "Client.h"
  2. #include <QString>
  3. #include <stdio.h>
  4. #include <QTcpSocket>
  5. #include <QStringList>
  6. #include <QTime>
  7. #include <QTimer>
  8. #include "App.h"
  9. #include "Settings.h"
  10. Client::Client(App *app, ActiveClient* ac):
  11. QWClient(),
  12. myActiveClient(ac),
  13. myApp(app),
  14. myConnectionRetries(0),
  15. myOnServerFlag(false),
  16. mySpamMutedFlag(false),
  17. myQWMutedFlag(false),
  18. myJoinMessageTimer(new QTimer()),
  19. myKeepNickTimer(new QTimer()),
  20. myFloodTimer(new QTimer()),
  21. myQWBroadcastFloodTimer(new QTimer()),
  22. mySpamBroadcastFloodTimer(new QTimer()),
  23. myJoinMessagePrinted(false),
  24. myJoinMessageScheduled(false),
  25. myMaxClients(0)
  26. {
  27. myJoinMessageTimer->setSingleShot(true);
  28. myKeepNickTimer->setSingleShot(true);
  29. myFloodTimer->setSingleShot(true);
  30. myQWBroadcastFloodTimer->setSingleShot(true);
  31. mySpamBroadcastFloodTimer->setSingleShot(true);
  32. }
  33. Client::~Client()
  34. {
  35. delete myJoinMessageTimer;
  36. delete myKeepNickTimer;
  37. delete myFloodTimer;
  38. delete myQWBroadcastFloodTimer;
  39. delete mySpamBroadcastFloodTimer;
  40. }
  41. void Client::connect(const char *host, quint16 port)
  42. {
  43. myJoinMessageScheduled = true; //Hi message only scheduled at bot connection
  44. QWClient::connect(host, port);
  45. }
  46. void Client::say(const QString &msg)
  47. {
  48. QString cmd = "say " + msg;
  49. sendCmd(cmd.toAscii().data());
  50. }
  51. void Client::sayTeam(const QString &msg)
  52. {
  53. QString cmd = "say_team " + msg;
  54. sendCmd(cmd.toAscii().data());
  55. }
  56. void Client::setTeam(const QString &msg)
  57. {
  58. sendCmd(QString("setinfo \"team\" \"" + msg + "\"").toAscii().data());
  59. }
  60. void Client::disconnect()
  61. {
  62. QWClient::disconnect();
  63. myOnServerFlag = false;
  64. }
  65. void Client::print(const QString &msg)
  66. {
  67. QString str;
  68. str = "[" + QTime::currentTime().toString(Qt::ISODate) + "] " + QString(host()) + ":" + QString::number(port()) + "> " + msg;
  69. QByteArray b = str.toAscii();
  70. Client::stripColor(b.data());
  71. str = QString::fromAscii(b.data());
  72. myApp->print(str);
  73. }
  74. void Client::setPlayerList(PlayerList &playerList)
  75. {
  76. myPlayerList = playerList;
  77. }
  78. void Client::onDisconnect()
  79. {
  80. print("Disconnected..\n");
  81. myOnServerFlag = false;
  82. }
  83. void Client::retryConnection()
  84. {
  85. if(myConnectionRetries == ConnectionRetries)
  86. {
  87. print("Giving up!\n");
  88. disconnect();
  89. myOnServerFlag = false;
  90. return;
  91. }
  92. print("Reconnecting...\n");
  93. reconnect();
  94. myConnectionRetries++;
  95. }
  96. bool Client::isQWMuted() const
  97. {
  98. return myQWMutedFlag;
  99. }
  100. bool Client::isSpamMuted() const
  101. {
  102. return mySpamMutedFlag;
  103. }
  104. void Client::parsePrintedLine()
  105. {
  106. Player player;
  107. bool parsed = false;
  108. quint16 lastMatchSize = 0;
  109. QByteArray playerName;
  110. QByteArray printLine(myPrintLine.toAscii());
  111. QWClient::stripColor(printLine.data());
  112. foreach(player, myPlayerList)
  113. {
  114. playerName = player.name.toAscii();
  115. QWClient::stripColor(playerName.data());
  116. if(printLine.startsWith(playerName) || (player.spectator && printLine.startsWith(QString("[SPEC] " + player.name).toAscii())))
  117. {
  118. if(player.spectator && printLine.startsWith("[SPEC] "))
  119. {
  120. if(lastMatchSize < (playerName.size() + 7))
  121. lastMatchSize = (playerName.size() + 7);
  122. }
  123. else if(lastMatchSize < playerName.size())
  124. {
  125. lastMatchSize = playerName.size();
  126. }
  127. parsed = true;
  128. }
  129. }
  130. if(!parsed)
  131. return;
  132. QString nick(myPrintLine.left(lastMatchSize));
  133. QString message(myPrintLine.right(myPrintLine.size() - lastMatchSize));
  134. QRegExp regex("^:\\s+\\.(spam|qw|help|qw_mute|qw_unmute|spam_mute|spam_unmute|lastmsgs)\\s*(.+)$");
  135. if(regex.indexIn(message) == -1)
  136. return;
  137. /* Flood prot */
  138. QTime currentTime = QTime::currentTime();
  139. int floodProtTime = Settings::globalInstance()->floodProtTime();
  140. if(myFloodTimer->isActive())
  141. {
  142. if(!myFloodMsgPrinted)
  143. {
  144. say("> FloodProt: Not so fast, wait " + QString::number(floodProtTime + currentTime.secsTo(myFloodTimerStart)) + " sec(s).");
  145. myFloodMsgPrinted = true;
  146. }
  147. return;
  148. }
  149. myFloodTimerStart = currentTime;
  150. myFloodTimer->start(floodProtTime*1000);
  151. myFloodMsgPrinted = false;
  152. QString command = regex.capturedTexts().at(1);
  153. QString args = regex.capturedTexts().at(2);
  154. if(command == "help")
  155. {
  156. //say("> Commands:");
  157. say("> Broadcast a message: .qw <message> and .spam <message>");
  158. //, beware of the floodprot limits 600s for .qw and 300s for .spam");
  159. say("> (Un)Mute: .qw_mute .qw_unmute or .spam_mute .spam_unmute");
  160. say("> Last 5 messages: .lastmsgs");
  161. return;
  162. }
  163. if(command == "qw" || command == "spam")
  164. {
  165. if(!args.trimmed().size())
  166. {
  167. say("> The format is ." + command + " <message>.");
  168. return;
  169. }
  170. /* Floodprot for broadcasting commands */
  171. if(command == "qw")
  172. {
  173. int qwFloodProtTime = Settings::globalInstance()->qwFloodProtTime();
  174. if(myQWBroadcastFloodTimer->isActive())
  175. {
  176. say("> FloodProt: Wait " + QString::number(qwFloodProtTime + currentTime.secsTo(myQWBroadcastFloodTimerStart)) + " secs before new .qw");
  177. return;
  178. }
  179. myQWBroadcastFloodTimerStart = currentTime;
  180. myQWBroadcastFloodTimer->start(qwFloodProtTime*1000);
  181. }
  182. else if(command == "spam")
  183. {
  184. int spamFloodProtTime = Settings::globalInstance()->spamFloodProtTime();
  185. if(mySpamBroadcastFloodTimer->isActive())
  186. {
  187. say("> FloodProt: Wait " + QString::number(spamFloodProtTime + currentTime.secsTo(mySpamBroadcastFloodTimerStart)) + " secs before new .spam");
  188. return;
  189. }
  190. mySpamBroadcastFloodTimerStart = currentTime;
  191. mySpamBroadcastFloodTimer->start(spamFloodProtTime*1000);
  192. }
  193. QString server(QString(host()) + ":" + QString::number(port()) + " " + QString::number(playerCount()) + "/" + QString::number(myMaxClients));
  194. QString message("-" + command + "- " + nick + " - " + server + " : " + args.trimmed());
  195. /* Broadcast within QW servers */
  196. myApp->broadcast(message, myActiveClient);
  197. /* Broadcast outside QW */
  198. nick = parseNameFun(nick); //for the irc message namefun must be removed.
  199. QString parsedMsg = parseNameFun(args.trimmed());
  200. if(!Settings::globalInstance()->developerMode())
  201. myApp->requestBroadcast(command, nick, server, args.trimmed());
  202. else
  203. myApp->requestBroadcast("dev", nick, server, parsedMsg);
  204. return;
  205. }
  206. if(command == "qw_mute")
  207. {
  208. say("> .qw Frequency Muted.");
  209. myQWMutedFlag = true;
  210. return;
  211. }
  212. if(command == "qw_unmute")
  213. {
  214. say("> .qw Frequency Unmuted.");
  215. myQWMutedFlag = false;
  216. return;
  217. }
  218. if(command == "spam_mute")
  219. {
  220. say("> .spam Frequency Muted.");
  221. mySpamMutedFlag = true;
  222. return;
  223. }
  224. if(command == "spam_unmute")
  225. {
  226. say("> .spam Frequency Unmuted.");
  227. mySpamMutedFlag = false;
  228. return;
  229. }
  230. if(command == "lastmsgs")
  231. {
  232. QStringList messages = myApp->lastMessages();
  233. if(!messages.size())
  234. {
  235. say("None");
  236. return;
  237. }
  238. QString msg;
  239. int i = 0;
  240. foreach(msg, messages)
  241. {
  242. if(++i > 5)
  243. break;
  244. say(msg);
  245. }
  246. return;
  247. }
  248. }
  249. int Client::playerCount() const
  250. {
  251. Player c;
  252. int pc = 0;
  253. foreach(c, myPlayerList)
  254. {
  255. if(c.spectator)
  256. continue;
  257. pc++;
  258. }
  259. return pc;
  260. }
  261. void Client::setMaxClients(int maxClients)
  262. {
  263. myMaxClients = maxClients;
  264. }
  265. int Client::maxClients() const
  266. {
  267. return myMaxClients;
  268. }
  269. void Client::onPrint(int, const char *msg)
  270. {
  271. if(!strlen(msg))
  272. return;
  273. QString text(msg);
  274. if(text.endsWith('\n'))
  275. {
  276. myPrintLine.append(text);
  277. parsePrintedLine();
  278. print(myPrintLine);
  279. myPrintLine.clear();
  280. }
  281. else
  282. {
  283. myPrintLine.append(text);
  284. }
  285. }
  286. bool Client::isOnServer() const
  287. {
  288. return myOnServerFlag;
  289. }
  290. void Client::onError(const char *description)
  291. {
  292. QString desc(description);
  293. if(desc == "Client Timed Out.")
  294. {
  295. print("Error (" + QString(description) + ")\n");
  296. }
  297. else
  298. {
  299. print("Error (" + QString(description) + ")\n");
  300. }
  301. myOnServerFlag = false;
  302. }
  303. void Client::onLevelChanged(int, const char *levelName, float, float, float, float, float, float, float, float, float, float)
  304. {
  305. print(QString(levelName) + "\n");
  306. myDownloadProgressPrintedFlag = false;
  307. mySpamMutedFlag = false;
  308. myQWMutedFlag = false;
  309. }
  310. void Client::onChallenge()
  311. {
  312. print("challenge\n");
  313. }
  314. void Client::onConnection()
  315. {
  316. print("connection\n");
  317. }
  318. void Client::onConnected()
  319. {
  320. print("connected\n");
  321. }
  322. void Client::onDownloadStarted(const char *fileName)
  323. {
  324. print("Download started " + QString(fileName) + "\n");
  325. }
  326. void Client::run()
  327. {
  328. if(!myJoinMessageTimer->isActive() && !myJoinMessagePrinted)
  329. {
  330. say("Hi, I am QWNET's bot, type .help to see my commands.");
  331. myJoinMessagePrinted = true;
  332. }
  333. /* Keep nick... Simply set name again after 10 secs */
  334. if(!myKeepNickTimer->isActive())
  335. {
  336. setName(Settings::globalInstance()->botName().toAscii().data());
  337. myKeepNickTimer->start(30000);
  338. }
  339. QWClient::run();
  340. }
  341. void Client::onOOBPrint(const char *msg)
  342. {
  343. print(QString(msg));
  344. }
  345. void Client::onStuffedCmd(const char *cmd)
  346. {
  347. QString strCmd(cmd);
  348. if(strCmd == "skins") //connection sequence complete
  349. {
  350. myConnectionRetries = 0;
  351. myOnServerFlag = true;
  352. /* Only say hi if hi is scheduled */
  353. if(myJoinMessageScheduled)
  354. {
  355. myJoinMessageTimer->start(Settings::globalInstance()->timeToSayHiAfterConnected()*1000);
  356. myJoinMessagePrinted = false;
  357. myJoinMessageScheduled = false;
  358. }
  359. }
  360. }
  361. void Client::onDownloadProgress(int percent)
  362. {
  363. if(!(percent % 10))
  364. {
  365. if(!myDownloadProgressPrintedFlag)
  366. {
  367. print("Download " + QString::number(percent) + "%\n");
  368. myDownloadProgressPrintedFlag = true;
  369. }
  370. }
  371. else
  372. {
  373. myDownloadProgressPrintedFlag = false;
  374. }
  375. }
  376. void Client::onDownloadFinished()
  377. {
  378. print("Download 100% finished.\n");
  379. }
  380. QString Client::parseNameFun(const QString &string)
  381. {
  382. QByteArray b(string.toAscii());
  383. QWClient::stripColor(b.data());
  384. return QString(b);
  385. }