4
0

pubcmds.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739
  1. /*
  2. * Copyright (C) 2000,2001 Florian Sander
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; either version 2
  7. * of the License, or (at your option) any later version.
  8. *
  9. * This program 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. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. static int nopubstats(char *chan)
  19. {
  20. Assert(chan);
  21. #if EGG_IS_MIN_VER(10503)
  22. if (ngetudef("nopubstats", chan) || ngetudef("nostats", chan))
  23. return 1;
  24. #endif
  25. return 0;
  26. }
  27. static int quietstats(char *chan)
  28. {
  29. Assert(chan);
  30. #if EGG_IS_MIN_VER(10503)
  31. if (ngetudef("quietstats", chan))
  32. return 1;
  33. #endif
  34. return 0;
  35. }
  36. static int stat_flood()
  37. {
  38. if (!maxstat_thr || !maxstat_time)
  39. return 0;
  40. if ((now - mstat_time) > maxstat_time) {
  41. mstat_time = now;
  42. mstat_thr = 0;
  43. }
  44. mstat_thr++;
  45. if (mstat_thr > maxstat_thr)
  46. return 1;
  47. return 0;
  48. }
  49. static int pub_top(char *nick, char *host, char *hand,
  50. char *channel, char *text)
  51. {
  52. char *toptext;
  53. if (nopubstats(channel))
  54. return 1;
  55. // check for flood
  56. if (stat_flood())
  57. return 1;
  58. reset_global_vars();
  59. glob_slang = slang_find(coreslangs, slang_chanlang_get(chanlangs, channel));
  60. putlog(LOG_CMDS, channel, "<<%s>> !%s! top %s", nick, hand, text);
  61. toptext = tell_ntop(channel, text, 0);
  62. if (!toptext)
  63. return 1;
  64. if (quietstats(channel))
  65. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, toptext);
  66. else
  67. dprintf(DP_HELP, "PRIVMSG %s :%s\n", channel, toptext);
  68. return 1;
  69. }
  70. static int pub_last(char *nick, char *host, char *hand,
  71. char *channel, char *text)
  72. {
  73. char *toptext;
  74. if (nopubstats(channel))
  75. return 1;
  76. if (stat_flood())
  77. return 1;
  78. reset_global_vars();
  79. glob_slang = slang_find(coreslangs, slang_chanlang_get(chanlangs, channel));
  80. putlog(LOG_CMDS, channel, "<<%s>> !%s! top10 %s", nick, hand, text);
  81. toptext = tell_ntop(channel, text, 1);
  82. if (!toptext)
  83. return 1;
  84. if (quietstats(channel))
  85. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, toptext);
  86. else
  87. dprintf(DP_HELP, "PRIVMSG %s :%s\n", channel, toptext);
  88. return 1;
  89. }
  90. static char *stats_pubcmd_reply;
  91. static char *tell_ntop(char *chan, char *params, int last)
  92. {
  93. char *par, *slang, *type, *word;
  94. int timerange, range, tmp, sorting, itype, place, start, len, replylen;
  95. int active_users;
  96. globstats *gs;
  97. locstats *ls;
  98. if (stats_pubcmd_reply) {
  99. nfree(stats_pubcmd_reply);
  100. stats_pubcmd_reply = NULL;
  101. }
  102. par = slang = type = word = NULL;
  103. ls = NULL;
  104. gs = NULL;
  105. timerange = S_TOTAL;
  106. type = "words";
  107. range = 10;
  108. itype = T_WORDS;
  109. // get pointer to the stats struct
  110. if (!(gs = findglobstats(chan))) {
  111. debug1("no globstats for %s", chan);
  112. return NULL;
  113. }
  114. glob_globstats = gs;
  115. // pars through params
  116. while (params[0]) {
  117. par = newsplit(&params);
  118. // check if param is a timerange
  119. if ((tmp = get_timerange(par)) != T_ERROR)
  120. timerange = tmp;
  121. // still no match? Then lets check if the param
  122. // is a range (top10, top20, etc...)
  123. else if ((tmp = atoi(par)))
  124. range = tmp;
  125. // still no match? Uhm... ok, maybe this is a
  126. else if ((tmp = slangtypetoi(par)) != T_ERROR) {
  127. itype = tmp;
  128. if (itype == T_WORD) {
  129. word = newsplit(&params);
  130. }
  131. type = par;
  132. } else
  133. debug1("Unknown parameter: %s", par);
  134. }
  135. // init language stuff
  136. glob_sorting = itype;
  137. glob_range = range;
  138. glob_timerange = timerange;
  139. // use special function if user requested sorting by a special word
  140. if (glob_sorting == T_WORD)
  141. return tell_top_word(chan, word, range, gs);
  142. // now sort the stats
  143. sortstats(gs, itype, timerange);
  144. active_users = countactivestatmembers(gs, 0, timerange,
  145. (itype >= 0) ? itype : T_LINES, 1);
  146. // now get the "entry phrase" for the topX
  147. if (!last)
  148. slang = getslang(100 + timerange);
  149. else
  150. slang = getslang(110 + timerange);
  151. // now allocate memory and sprintf the start of the repy into it
  152. stats_pubcmd_reply = nmalloc(strlen(slang) + 1);
  153. strcpy(stats_pubcmd_reply, slang);
  154. // if we sorted by a special type, transform the sorting index to
  155. // a usable index to access the stat-array
  156. if (itype < 0)
  157. sorting = (itype * -1) + (TOTAL_TYPES - 1);
  158. else
  159. sorting = itype;
  160. // if we want to show the last users, then adjust the range
  161. if (last)
  162. range = active_users - range + 10;
  163. start = range - 10;
  164. if (start < 1)
  165. start = 1;
  166. place = 0;
  167. for (ls = gs->slocal[timerange][sorting]; ls; ls = ls->snext[timerange][sorting]) {
  168. place++;
  169. if (place > range)
  170. break;
  171. if (itype >= 0)
  172. if (!ls->values[timerange][itype])
  173. break;
  174. if (place >= start) {
  175. replylen = strlen(stats_pubcmd_reply);
  176. len = 3 + strlen(ls->user) + 10 + 6 + 1;
  177. stats_pubcmd_reply = nrealloc(stats_pubcmd_reply, replylen + len);
  178. if (itype >= 0)
  179. snprintf(stats_pubcmd_reply + replylen, len, " %d. %s (%ld)", place, ls->user,
  180. ls->values[timerange][itype]);
  181. else if (itype == T_WPL)
  182. snprintf(stats_pubcmd_reply + replylen, len, " %d. %s (%.2f)", place, ls->user,
  183. ls->values[timerange][T_WORDS] ?
  184. (ls->values[timerange][T_WORDS] / ls->values[timerange][T_LINES]) :
  185. 0.0);
  186. else if (itype == T_IDLE)
  187. snprintf(stats_pubcmd_reply + replylen, len, " %d. %s (%.2f)", place, ls->user,
  188. ls->values[timerange][T_LINES] ?
  189. (ls->values[timerange][T_MINUTES] / ls->values[timerange][T_LINES]) :
  190. 0.0);
  191. else
  192. snprintf(stats_pubcmd_reply + replylen, len, " %d. %s (ERROR)", place, ls->user);
  193. }
  194. }
  195. stats_pubcmd_reply = nrealloc(stats_pubcmd_reply, strlen(stats_pubcmd_reply) + 1);
  196. return stats_pubcmd_reply;
  197. }
  198. static char *tell_top_word(char *chan, char *word, int range, globstats *gs)
  199. {
  200. locstats *ls;
  201. char buf[100], *slang;
  202. int num, itype;
  203. Context;
  204. Assert(!stats_pubcmd_reply);
  205. word = newsplit(&word);
  206. strlower(word);
  207. setword(gs, word);
  208. glob_word = word;
  209. sortstats(gs, T_WORD, 1);
  210. if (range > 0)
  211. slang = getslang(120); // "Top <?range?>("<?word?>"):"
  212. else
  213. slang = getslang(130); // Last <?range?>("<?word?>"):
  214. stats_pubcmd_reply = nmalloc(strlen(slang) + 1);
  215. strcpy(stats_pubcmd_reply, slang);
  216. itype = (T_WORD * (-1)) + TOTAL_TYPES - 1;
  217. if (range < 0) {
  218. num = countactivestatmembers_by_word(gs, 1, 1);
  219. range = num - (range * (-1));
  220. if (range < 0)
  221. range = num;
  222. }
  223. glob_place = 0;
  224. for (ls = gs->slocal[S_TODAY][itype]; ls; ls = ls->snext[S_TODAY][itype]) {
  225. if (!listsuser(ls, chan))
  226. continue;
  227. glob_place++;
  228. if ((glob_place > range) || !ls->word) {
  229. break;
  230. }
  231. if (glob_place >= range - 10) {
  232. snprintf(buf, sizeof(buf), " %d. %s(%d)", glob_place, ls->user, ls->word->nr);
  233. stats_pubcmd_reply = nrealloc(stats_pubcmd_reply, strlen(stats_pubcmd_reply) + strlen(buf) + 1);
  234. strcat(stats_pubcmd_reply, buf);
  235. }
  236. }
  237. Context;
  238. return stats_pubcmd_reply;
  239. }
  240. static int pub_place(char *nick, char *host, char *hand,
  241. char *channel, char *text)
  242. {
  243. char *reply;
  244. Context;
  245. if (nopubstats(channel))
  246. return 1;
  247. if (stat_flood())
  248. return 1;
  249. putlog(LOG_CMDS, channel, "<<%s>> !%s! place %s", nick, hand, text);
  250. reply = tell_place(nick, hand, channel, text);
  251. if (quietstats(channel)) {
  252. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, reply);
  253. } else {
  254. dprintf(DP_HELP, "PRIVMSG %s :%s\n", channel, reply);
  255. }
  256. Context;
  257. return 1;
  258. }
  259. static char *tell_place(char *nick, char *hand, char *channel, char *text)
  260. {
  261. globstats *gs;
  262. struct stats_member *m;
  263. struct stats_userlist *su;
  264. struct userrec *u;
  265. char *who, *slang, *par, *type;
  266. int place = 0;
  267. int itype;
  268. int itmp;
  269. int today;
  270. Context;
  271. // at first, check for flood...
  272. reset_global_vars();
  273. glob_slang = slang_find(coreslangs, slang_chanlang_get(chanlangs, channel));
  274. // ... get the global stat-struct for the channel ...
  275. gs = findglobstats(channel);
  276. if (!gs) {
  277. debug1("Stats.mod: Couldn't exec !place, I don't have any statistics in %s.", channel);
  278. return "NOSTATS!";
  279. }
  280. glob_globstats = gs;
  281. // .. now init vars ...
  282. m = NULL;
  283. u = NULL;
  284. su = NULL;
  285. who = slang = type = NULL;
  286. itype = T_ERROR;
  287. today = S_TOTAL;
  288. // parse params...
  289. while (text[0]) {
  290. par = newsplit(&text);
  291. // maybe par is a stat-type?
  292. if ((itype == T_ERROR) && ((itmp = slangtypetoi(par)) != T_ERROR))
  293. itype = itmp;
  294. // or an user in the stats-userbase?
  295. else if (!who && (su = findsuser_by_name(par)))
  296. who = su->user;
  297. // or at least a user in the eggdrop userbase?
  298. else if (!who && (u = get_user_by_handle(userlist, par)))
  299. who = u->handle;
  300. else if ((itmp = get_timerange(par)) != T_ERROR)
  301. today = itmp;
  302. // oh.. what now? We can't know if it's a wrong type or a non-existant user,
  303. // so let's assume it is a user and return an error
  304. else {
  305. glob_nick = par;
  306. return getslang(220); // "I don't have any stats about <?nick?>."
  307. }
  308. }
  309. // if no type was specified, just default to "words"
  310. if (itype == T_ERROR)
  311. itype = T_WORDS;
  312. glob_sorting = itype;
  313. glob_timerange = today;
  314. // if we still don't know whose place we should show, then just asume
  315. // that the triggering user wants to know his own place (how selfish.. ^_^)
  316. if (!who) {
  317. // at first, check if we already know this user by handle
  318. if (!(!strcasecmp(hand, "*"))) {
  319. who = hand;
  320. } else {
  321. // now try to get the user from the stats-userbase
  322. // maybe the user is on the channel and we already found
  323. // the matching username?
  324. m = getschanmember(nick, channel);
  325. if (m && m->user)
  326. who = m->user->user;
  327. // not? Ok, then this user got a problem...
  328. // we _could_ check for the user's host here and try to resolve his
  329. // susername this way, but I think that's not worth the effort
  330. }
  331. // still no match? Ouch! Then we probably don't have any stats about this
  332. // poor user...
  333. if (!who) {
  334. glob_nick = nick;
  335. return getslang(221); // "I don't have any stats about you."
  336. }
  337. }
  338. Assert(who);
  339. Assert(itype != T_ERROR);
  340. Assert(gs);
  341. // sort the stats
  342. sortstats(gs, itype, today);
  343. // and get the place of the user
  344. place = getplace(gs, today, itype, who);
  345. // if ls is NULL now, then the user doesn't have any stats in this chan
  346. if (!place) {
  347. glob_nick = who;
  348. return getslang(220); // "I don't have any stats about <?nick?>."
  349. } else {
  350. // stats found, so let's output them
  351. glob_nick = who;
  352. glob_place = place;
  353. // there are 4 slang-entries for today, this week, etc
  354. return getslang(200 + today);
  355. }
  356. Context;
  357. }
  358. static int pub_stat(char *nick, char *host, char *hand,
  359. char *channel, char *text)
  360. {
  361. char *reply;
  362. Context;
  363. if (stat_flood())
  364. return 0;
  365. if (nopubstats(channel))
  366. return 0;
  367. putlog(LOG_CMDS, channel, "<<%s>> !%s! stat %s", nick, hand, text);
  368. reply = tell_stat(nick, channel, text);
  369. Assert(reply);
  370. if (quietstats(channel))
  371. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, reply);
  372. else
  373. dprintf(DP_HELP, "PRIVMSG %s :%s\n", channel, reply);
  374. Context;
  375. return 1;
  376. }
  377. static char *tell_stat(char *nick, char *channel, char *text)
  378. {
  379. /*
  380. char *who, *tosend, , , ;
  381. int itype, first;
  382. struct stats_memberlist *m;
  383. struct stats_userlist *su;
  384. #if EGG_IS_MIN_VER(10500)
  385. struct chanset_t *chan;
  386. #endif
  387. */
  388. char *par, *tosend, buf[50], *stmp, what[128], *pwhat, *type, *dur;
  389. int i, timerange, first, itype;
  390. struct stats_userlist *utmp, *user;
  391. struct stats_member *member;
  392. locstats *ls;
  393. Context;
  394. if (stats_pubcmd_reply) {
  395. nfree(stats_pubcmd_reply);
  396. stats_pubcmd_reply = NULL;
  397. }
  398. reset_global_vars();
  399. timerange = S_TOTAL;
  400. tosend = nmalloc(500);
  401. tosend[0] = 0;
  402. user = NULL;
  403. type = dur = NULL;
  404. glob_slang = slang_find(coreslangs, slang_chanlang_get(chanlangs, channel));
  405. glob_globstats = findglobstats(channel);
  406. while (text[0]) {
  407. par = newsplit(&text);
  408. if ((i = get_timerange(par)) != T_ERROR)
  409. timerange = i;
  410. else if ((utmp = findsuser_by_name(par)))
  411. user = utmp;
  412. else {
  413. member = getschanmember(par, channel);
  414. if (member && member->user && !suser_nostats(member->user))
  415. user = member->user;
  416. else {
  417. glob_nick = par;
  418. nfree(tosend);
  419. return SLNOSTATSABOUTSOMEONE;
  420. }
  421. }
  422. }
  423. if (!user) {
  424. member = getschanmember(nick, channel);
  425. if (member && member->user && !suser_nostats(member->user))
  426. user = member->user;
  427. if (!user) {
  428. nfree(tosend);
  429. glob_nick = nick;
  430. return SLNOSTATSABOUTYOU;
  431. }
  432. }
  433. ls = findlocstats(channel, user->user);
  434. glob_locstats = ls;
  435. if (!ls) {
  436. glob_nick = user->user;
  437. nfree(tosend);
  438. return SLNOSTATSABOUTSOMEONE;
  439. } else {
  440. what[0] = 0;
  441. pwhat = what;
  442. strncpy(pwhat, stat_reply, 127);
  443. pwhat[127] = 0;
  444. first = 1;
  445. while (strlen(pwhat) > 0) {
  446. type = newsplit(&pwhat);
  447. itype = typetoi(type);
  448. if ((itype < 0) && (itype != T_WPL) && (itype != T_IDLE))
  449. continue;
  450. if (!first) {
  451. // if this isn't the first run, attach a "," to the string to
  452. // seperate the values.
  453. strncat(tosend, ",", 500);
  454. } else {
  455. first = 0;
  456. }
  457. if (itype == T_MINUTES) {
  458. dur = stats_duration(ls->values[timerange][T_MINUTES] * 60, 6);
  459. stmp = getslangtype("minutes");
  460. snprintf(buf, sizeof(buf), " %s: %s", stmp, dur);
  461. strncat(tosend, buf, 500);
  462. } else if (itype >= 0) {
  463. // same as usual: use 10 bytes for the integer-string
  464. stmp = getslangtype(type);
  465. snprintf(buf, sizeof(buf), " %ld %s", ls->values[timerange][itype], stmp);
  466. strncat(tosend, buf, 500);
  467. } else if ((itype == T_WPL) && (ls->values[timerange][T_LINES] != 0)) {
  468. stmp = getslangtype("wpl");
  469. // Thanks to Algirdas 'QQ' Kepezinskas for tracking down
  470. // the bug which was placed in this line.
  471. snprintf(buf, sizeof(buf), " %.2f %s", (float) ls->values[timerange][T_WORDS] / (float) ls->values[timerange][T_LINES], stmp);
  472. strncat(tosend, buf, 500);
  473. } else if ((itype == T_IDLE) && (ls->values[timerange][T_LINES] != 0)) {
  474. stmp = getslangtype("idle");
  475. snprintf(buf, sizeof(buf), " %.2f %s", (float) ls->values[timerange][T_MINUTES] / (float) ls->values[timerange][T_LINES], stmp);
  476. strncat(tosend, buf, 500);
  477. }
  478. }
  479. }
  480. i = strlen(user->user) + 2 + strlen(tosend) + 1;
  481. stats_pubcmd_reply= nmalloc(i);
  482. snprintf(stats_pubcmd_reply, i, "%s: %s", user->user, tosend);
  483. nfree(tosend);
  484. return stats_pubcmd_reply;
  485. }
  486. static int pub_wordstats(char *nick, char *host, char *hand,
  487. char *channel, char *text)
  488. {
  489. Context;
  490. if (nopubstats(channel))
  491. return 1;
  492. putlog(LOG_CMDS, channel, "<<%s>> !%s! wordstats %s", nick, hand, text);
  493. tell_wordstats(nick, channel, hand, channel, text);
  494. Context;
  495. return 0;
  496. }
  497. static void tell_wordstats(char *nick, char *dest, char *hand, char *channel, char *text)
  498. {
  499. locstats *ls;
  500. wordstats *ws;
  501. char *who, *tosend, *slang;
  502. int i;
  503. #if EGG_IS_MIN_VER(10500)
  504. struct chanset_t *chan;
  505. #endif
  506. Context;
  507. reset_global_vars();
  508. glob_slang = slang_find(coreslangs, slang_chanlang_get(chanlangs, channel));
  509. if (stat_flood())
  510. return;
  511. #if EGG_IS_MIN_VER(10500)
  512. if (!strcasecmp(channel, dest)) {
  513. chan = findchan_by_dname(dest);
  514. if (chan)
  515. dest = chan->name;
  516. }
  517. #endif
  518. if (text[0] == 0) {
  519. who = nmalloc(strlen(hand) + 1);
  520. strcpy(who, hand);
  521. } else {
  522. who = nmalloc(strlen(text) + 1);
  523. strcpy(who, text);
  524. }
  525. if (who[0] == '*') {
  526. glob_nick = nick;
  527. if (quietstats(dest))
  528. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, SLNOSTATSABOUTYOU);
  529. else
  530. dprintf(DP_HELP, "PRIVMSG %s :%s\n", dest, SLNOSTATSABOUTYOU);
  531. nfree(who);
  532. return;
  533. }
  534. ls = findlocstats(channel, who);
  535. glob_locstats = ls;
  536. if (!ls) {
  537. glob_nick = who;
  538. if (quietstats(dest))
  539. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, SLNOSTATSABOUTSOMEONE);
  540. else
  541. dprintf(DP_HELP, "PRIVMSG %s :%s\n", dest, SLNOSTATSABOUTSOMEONE);
  542. } else {
  543. if (!ls->words) {
  544. glob_nick = who;
  545. if (quietstats(dest))
  546. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, SLNOWORDSTATS);
  547. else
  548. dprintf(DP_HELP, "PRIVMSG %s :%s\n", dest, SLNOWORDSTATS);
  549. } else {
  550. slang = SLUSERSMOSTUSEDWORDS;
  551. if (quietstats(dest)) {
  552. tosend = nmalloc(13 + strlen(nick) + strlen(slang) + 1);
  553. sprintf(tosend, "NOTICE %s :%s", nick, slang);
  554. } else {
  555. tosend = nmalloc(14 + strlen(dest) + strlen(slang) + 1);
  556. sprintf(tosend, "PRIVMSG %s :%s", dest, slang);
  557. }
  558. i = 0;
  559. sortwordstats(ls, NULL);
  560. ws = ls->words;
  561. while (ws && (i < 10)) {
  562. i++;
  563. tosend = nrealloc(tosend, 14 + strlen(tosend) + 5 + strlen(ws->word) + 10 + 1);
  564. sprintf(tosend, "%s %d. %s (%d)", tosend, i, ws->word, ws->nr);
  565. ws = ws->next;
  566. }
  567. dprintf(DP_HELP, "%s\n", tosend);
  568. nfree(tosend);
  569. }
  570. }
  571. nfree(who);
  572. Context;
  573. }
  574. static int pub_topwords(char *nick, char *host, char *hand,
  575. char *channel, char *text)
  576. {
  577. Context;
  578. if (nopubstats(channel))
  579. return 1;
  580. putlog(LOG_CMDS, channel, "<<%s>> !%s! topwords %s", nick, hand, text);
  581. tell_topwords(nick, channel, hand, channel);
  582. Context;
  583. return 0;
  584. }
  585. static void tell_topwords(char *nick, char *dest, char *hand, char *channel)
  586. {
  587. globstats *gs;
  588. wordstats *ws;
  589. char *tosend, *slang;
  590. int i;
  591. #if EGG_IS_MIN_VER(10500)
  592. struct chanset_t *chan;
  593. #endif
  594. Context;
  595. if (stat_flood())
  596. return;
  597. reset_global_vars();
  598. glob_slang = slang_find(coreslangs, slang_chanlang_get(chanlangs, channel));
  599. #if EGG_IS_MIN_VER(10500)
  600. if (!strcasecmp(channel, dest)) {
  601. chan = findchan_by_dname(dest);
  602. if (chan)
  603. dest = chan->name;
  604. }
  605. #endif
  606. gs = findglobstats(channel);
  607. glob_globstats = gs;
  608. if (!gs) {
  609. return;
  610. }
  611. do_globwordstats(gs);
  612. ws = gs->words;
  613. if (!ws) {
  614. if (quietstats(dest))
  615. dprintf(DP_HELP, "NOTICE %s :I don't have any wordstats in %s\n", nick, SLNOCHANWORDSTATS);
  616. else
  617. dprintf(DP_HELP, "PRIVMSG %s :I don't have any wordstats in %s\n", dest, SLNOCHANWORDSTATS);
  618. return;
  619. }
  620. glob_nick = nick;
  621. slang = SLCHANSMOSTUSEDWORDS;
  622. if (quietstats(dest)) {
  623. tosend = nmalloc(13 + strlen(nick) + strlen(slang) + 1);
  624. sprintf(tosend, "NOTICE %s :%s", nick, slang);
  625. } else {
  626. tosend = nmalloc(14 + strlen(dest) + strlen(slang) + 1);
  627. sprintf(tosend, "PRIVMSG %s :%s", dest, slang);
  628. }
  629. i = 0;
  630. while (ws && (i < 10)) {
  631. i++;
  632. tosend = nrealloc(tosend, 14 + strlen(tosend) + 5 + strlen(ws->word) + 10);
  633. sprintf(tosend, "%s %d. %s (%d)", tosend, i, ws->word, ws->nr);
  634. ws = ws->next;
  635. }
  636. dprintf(DP_HELP, "%s\n", tosend);
  637. nfree(tosend);
  638. Context;
  639. }
  640. static char *cmd_lastspoke(char *chan, char *text)
  641. {
  642. char *user;
  643. globstats gs;
  644. if (stats_pubcmd_reply) {
  645. nfree(stats_pubcmd_reply);
  646. stats_pubcmd_reply = NULL;
  647. }
  648. reset_global_vars();
  649. glob_slang = slang_find(coreslangs, slang_chanlang_get(chanlangs, chan));
  650. user = newsplit(&text);
  651. glob_nick = user;
  652. glob_globstats = findglobstats(chan);
  653. glob_locstats = findlocstats(chan, user);
  654. if (!glob_locstats) {
  655. if (!glob_globstats) {
  656. globstats_init(&gs);
  657. gs.chan = chan;
  658. }
  659. return getslang(220);
  660. }
  661. if (!glob_locstats->lastspoke)
  662. return getslang(400);
  663. return getslang(405);
  664. }
  665. static int pub_lastspoke(char *nick, char *host, char *hand,
  666. char *channel, char *text)
  667. {
  668. char *reply;
  669. Context;
  670. if (nopubstats(channel))
  671. return 1;
  672. if (stat_flood())
  673. return 1;
  674. putlog(LOG_CMDS, channel, "<<%s>> !%s! lastspoke %s", nick, hand, text);
  675. reply = cmd_lastspoke(channel, text);
  676. if (quietstats(channel)) {
  677. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, reply);
  678. } else {
  679. dprintf(DP_HELP, "PRIVMSG %s :%s\n", channel, reply);
  680. }
  681. Context;
  682. return 1;
  683. }
  684. static cmd_t stats_pub[] =
  685. {
  686. {"!place", "", pub_place, 0},
  687. {"!stat", "", pub_stat, 0},
  688. {"!wordstats", "", pub_wordstats, 0},
  689. {"!topwords", "", pub_topwords, 0},
  690. {"!top", "", pub_top, 0},
  691. {"!last", "", pub_last, 0},
  692. {"!lastspoke", "", pub_lastspoke, 0},
  693. {0, 0, 0, 0}
  694. };