Client.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  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. myJoinMessagePrinted(false)
  20. {
  21. myEndFloodTime = QTime::currentTime();
  22. myQWBroadcastFloodTime = myEndFloodTime;
  23. mySpamBroadcastFloodTime = myEndFloodTime;
  24. myJoinMessageTimer->setSingleShot(true);
  25. }
  26. Client::~Client()
  27. {
  28. delete myJoinMessageTimer;
  29. }
  30. void Client::say(const QString &msg)
  31. {
  32. QString cmd = "say " + msg;
  33. sendCmd(cmd.toAscii().data());
  34. }
  35. void Client::sayTeam(const QString &msg)
  36. {
  37. QString cmd = "say_team " + msg;
  38. sendCmd(cmd.toAscii().data());
  39. }
  40. void Client::setTeam(const QString &msg)
  41. {
  42. sendCmd(QString("setinfo \"team\" \"" + msg + "\"").toAscii().data());
  43. }
  44. void Client::disconnect()
  45. {
  46. QWClient::disconnect();
  47. myOnServerFlag = false;
  48. }
  49. void Client::print(const QString &msg)
  50. {
  51. QString str;
  52. str = "[" + QTime::currentTime().toString(Qt::ISODate) + "] " + QString(host()) + ":" + QString::number(port()) + "> " + msg;
  53. QByteArray b = str.toAscii();
  54. Client::stripColor(b.data());
  55. str = QString::fromAscii(b.data());
  56. myApp->print(str);
  57. }
  58. void Client::setPlayerList(PlayerList &playerList)
  59. {
  60. myPlayerList = playerList;
  61. }
  62. void Client::onDisconnect()
  63. {
  64. print("Disconnected..\n");
  65. myOnServerFlag = false;
  66. }
  67. void Client::retryConnection()
  68. {
  69. if(myConnectionRetries == ConnectionRetries)
  70. {
  71. print("Giving up!\n");
  72. disconnect();
  73. myOnServerFlag = false;
  74. return;
  75. }
  76. print("Reconnecting...\n");
  77. reconnect();
  78. myConnectionRetries++;
  79. }
  80. bool Client::isQWMuted() const
  81. {
  82. return myQWMutedFlag;
  83. }
  84. bool Client::isSpamMuted() const
  85. {
  86. return mySpamMutedFlag;
  87. }
  88. void Client::parsePrintedLine()
  89. {
  90. Player player;
  91. bool parsed = false;
  92. quint16 lastMatchSize = 0;
  93. QByteArray playerName;
  94. QByteArray printLine(myPrintLine.toAscii());
  95. QWClient::stripColor(printLine.data());
  96. foreach(player, myPlayerList)
  97. {
  98. playerName = player.name.toAscii();
  99. QWClient::stripColor(playerName.data());
  100. if(printLine.startsWith(playerName) || (player.spectator && printLine.startsWith(QString("[SPEC] " + player.name).toAscii())))
  101. {
  102. if(player.spectator && printLine.startsWith("[SPEC] "))
  103. {
  104. if(lastMatchSize < (playerName.size() + 7))
  105. lastMatchSize = (playerName.size() + 7);
  106. }
  107. else if(lastMatchSize < playerName.size())
  108. {
  109. lastMatchSize = playerName.size();
  110. }
  111. parsed = true;
  112. }
  113. }
  114. if(!parsed)
  115. return;
  116. QString nick(myPrintLine.left(lastMatchSize));
  117. QString message(myPrintLine.right(myPrintLine.size() - lastMatchSize));
  118. QRegExp regex("^:\\s+\\.(spam|qw|help|qw_mute|qw_unmute|spam_mute|spam_unmute)\\s*(.+)$");
  119. if(regex.indexIn(message) == -1)
  120. return;
  121. /* Flood prot */
  122. QTime currentTime = QTime::currentTime();
  123. int timeLeft = currentTime.secsTo(myEndFloodTime);
  124. if(timeLeft > 0)
  125. {
  126. if(!myFloodMsgPrinted)
  127. {
  128. say("> FloodProt: Not so fast, wait " + QString::number(timeLeft) + " sec(s).");
  129. myFloodMsgPrinted = true;
  130. }
  131. return;
  132. }
  133. myEndFloodTime = QTime::currentTime().addSecs(Settings::globalInstance()->floodProtTime());
  134. myFloodMsgPrinted = false;
  135. QString command = regex.capturedTexts().at(1);
  136. QString args = regex.capturedTexts().at(2);
  137. if(command == "help")
  138. {
  139. say("> Commands:");
  140. say("> Broadcast a message: .qw <message> and .spam <message>, beware of the floodprot limits 600s for .qw and 300s for .spam");
  141. say("> Mute/Unmute: .qw_mute and .qw_unmute or .spam_mute or .spam_unmute");
  142. return;
  143. }
  144. if(command == "qw" || command == "spam")
  145. {
  146. if(!args.trimmed().size())
  147. {
  148. say("> The format is ." + command + " <message>.");
  149. return;
  150. }
  151. if(command == "qw")
  152. {
  153. timeLeft = currentTime.secsTo(myQWBroadcastFloodTime);
  154. if(timeLeft > 0)
  155. {
  156. say("> FloodProt: Wait " + QString::number(timeLeft) + " sec(s) before broadcasting a new .qw message.");
  157. return;
  158. }
  159. myQWBroadcastFloodTime = currentTime.addSecs(Settings::globalInstance()->qwFloodProtTime());
  160. }
  161. else if(command == "spam")
  162. {
  163. timeLeft = currentTime.secsTo(mySpamBroadcastFloodTime);
  164. if(timeLeft > 0)
  165. {
  166. say("> FloodProt: Wait " + QString::number(timeLeft) + " sec(s) before broadcasting a new .spam message.");
  167. return;
  168. }
  169. mySpamBroadcastFloodTime = currentTime.addSecs(Settings::globalInstance()->spamFloodProtTime());
  170. }
  171. QString server(QString(host()) + ":" + QString::number(port()));
  172. QString message("-" + command + "- " + nick + " - " + server + " : " + args.trimmed());
  173. /* Broadcast within QW servers */
  174. myApp->broadcast(message, myActiveClient);
  175. /* Broadcast outside QW */
  176. nick = parseNameFun(nick); //for the irc message namefun must be removed.
  177. QString parsedMsg = parseNameFun(args.trimmed());
  178. myApp->requestBroadcast("dev", nick, server, parsedMsg);
  179. //myApp->requestBroadcast(command, nick, server, args.trimmed());
  180. return;
  181. }
  182. if(command == "qw_mute")
  183. {
  184. say("> .qw Frequency Muted.");
  185. myQWMutedFlag = true;
  186. return;
  187. }
  188. if(command == "qw_unmute")
  189. {
  190. say("> .qw Frequency Unmuted.");
  191. myQWMutedFlag = false;
  192. return;
  193. }
  194. if(command == "spam_mute")
  195. {
  196. say("> .spam Frequency Muted.");
  197. mySpamMutedFlag = true;
  198. return;
  199. }
  200. if(command == "spam_unmute")
  201. {
  202. say("> .spam Frequency Unmuted.");
  203. mySpamMutedFlag = false;
  204. return;
  205. }
  206. }
  207. void Client::onPrint(int, const char *msg)
  208. {
  209. if(!strlen(msg))
  210. return;
  211. QString text(msg);
  212. if(text.endsWith('\n'))
  213. {
  214. myPrintLine.append(text);
  215. parsePrintedLine();
  216. print(myPrintLine);
  217. myPrintLine.clear();
  218. }
  219. else
  220. {
  221. myPrintLine.append(text);
  222. }
  223. }
  224. bool Client::isOnServer() const
  225. {
  226. return myOnServerFlag;
  227. }
  228. void Client::onError(const char *description)
  229. {
  230. QString desc(description);
  231. if(desc == "Client Timed Out.")
  232. {
  233. print("Error (" + QString(description) + ")\n");
  234. }
  235. else
  236. {
  237. print("Error (" + QString(description) + ")\n");
  238. }
  239. myOnServerFlag = false;
  240. }
  241. void Client::onLevelChanged(int, const char *levelName, float, float, float, float, float, float, float, float, float, float)
  242. {
  243. print(QString(levelName) + "\n");
  244. myDownloadProgressPrintedFlag = false;
  245. mySpamMutedFlag = false;
  246. myQWMutedFlag = false;
  247. }
  248. void Client::onChallenge()
  249. {
  250. print("challenge\n");
  251. }
  252. void Client::onConnection()
  253. {
  254. print("connection\n");
  255. }
  256. void Client::onConnected()
  257. {
  258. print("connected\n");
  259. }
  260. void Client::onDownloadStarted(const char *fileName)
  261. {
  262. print("Download started " + QString(fileName) + "\n");
  263. }
  264. void Client::run()
  265. {
  266. if(!myJoinMessageTimer->isActive() && !myJoinMessagePrinted)
  267. {
  268. say("Hi, I am QWNET's bot, type .help to see my commands.");
  269. myJoinMessagePrinted = true;
  270. }
  271. QWClient::run();
  272. }
  273. void Client::onOOBPrint(const char *msg)
  274. {
  275. print(QString(msg));
  276. }
  277. void Client::onStuffedCmd(const char *cmd)
  278. {
  279. QString strCmd(cmd);
  280. if(strCmd == "skins") //connection sequence complete
  281. {
  282. myConnectionRetries = 0;
  283. myOnServerFlag = true;
  284. myJoinMessageTimer->start(Settings::globalInstance()->timeToSayHiAfterConnected()*1000);
  285. myJoinMessagePrinted = false;
  286. }
  287. }
  288. void Client::onDownloadProgress(int percent)
  289. {
  290. if(!(percent % 10))
  291. {
  292. if(!myDownloadProgressPrintedFlag)
  293. {
  294. print("Download " + QString::number(percent) + "%\n");
  295. myDownloadProgressPrintedFlag = true;
  296. }
  297. }
  298. else
  299. {
  300. myDownloadProgressPrintedFlag = false;
  301. }
  302. }
  303. void Client::onDownloadFinished()
  304. {
  305. print("Download 100% finished.\n");
  306. }
  307. QString Client::parseNameFun(const QString &string)
  308. {
  309. QByteArray b(string.toAscii());
  310. QWClient::stripColor(b.data());
  311. return QString(b);
  312. }