sensors.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  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 sensor_msgm(char *nick, char *uhost, char *hand, char *chan, char *rest)
  19. {
  20. int i;
  21. char buf[511];
  22. struct stats_memberlist *m;
  23. globstats *gs;
  24. if (nostats(chan))
  25. return 0;
  26. strncpy(buf, rest, 510);
  27. buf[510] = 0;
  28. rest = buf;
  29. gs = findglobstats(chan);
  30. add_chanlog(gs, nick, rest, SL_PRIVMSG);
  31. m = nick2suser(nick, chan);
  32. if(!use_userfile) {
  33. if (!m) {
  34. putlog(LOG_LEV5, chan, "!m (%s)", nick);
  35. check_for_url(nick, chan, rest);
  36. return 0;
  37. }
  38. if (!m->user) {
  39. putlog(LOG_LEV5, chan, "!m->user (%s)", nick);
  40. check_for_url(nick, chan, rest);
  41. return 0;
  42. }
  43. check_for_url(m->user->user, chan, rest);
  44. // if there's no link to the stats, call initstats() which either
  45. // returns an existing stats struct, or initializes a new one
  46. if (!m->stats)
  47. m->stats = initstats(chan, m->user->user);
  48. nincrstats(m->stats, T_WORDS, countwords(rest));
  49. nincrstats(m->stats, T_LETTERS, strlen(rest));
  50. nincrstats(m->stats, T_LINES, 1);
  51. i = countsmileys(rest);
  52. if (i)
  53. nincrstats(m->stats, T_SMILEYS, i);
  54. i = countquestions(rest);
  55. if (i)
  56. nincrstats(m->stats, T_QUESTIONS, i);
  57. addquote(hand, gs, rest, m->stats);
  58. calcwordstats(hand, gs, rest, m->stats);
  59. } else {
  60. if (hand[0] == '*') {
  61. putlog(LOG_LEV5, chan, "hand[0] == '*' (%s)", nick);
  62. check_for_url(nick, chan, rest);
  63. return 0;
  64. }
  65. check_for_url(hand, chan, rest);
  66. incrstats(hand, chan, T_WORDS, countwords(rest), 0);
  67. incrstats(hand, chan, T_LETTERS, strlen(rest), 0);
  68. incrstats(hand, chan, T_LINES, 1, 0);
  69. i = countsmileys(rest);
  70. if (i)
  71. incrstats(hand, chan, T_SMILEYS, i, 0);
  72. i = countquestions(rest);
  73. if (i)
  74. incrstats(hand, chan, T_QUESTIONS, i, 0);
  75. addquote(hand, gs, rest, NULL);
  76. calcwordstats(hand, gs, rest, NULL);
  77. }
  78. return 0;
  79. }
  80. static void sensor_minutely()
  81. {
  82. struct chanset_t *chan;
  83. memberlist *m;
  84. struct stats_chanset *ch;
  85. struct stats_memberlist *mm;
  86. Context;
  87. if (use_userfile) {
  88. for (chan = chanset; chan; chan = chan->next) {
  89. #ifndef OLDBOT
  90. if (nostats(chan->dname))
  91. #else
  92. if (nostats(chan->name))
  93. #endif
  94. continue;
  95. if (chan->channel.members > 0) {
  96. for (m = chan->channel.member; m; m = m->next) {
  97. #ifndef OLDBOT
  98. if (m->user != NULL)
  99. incrstats(m->user->handle, chan->dname, T_MINUTES, 1, 0);
  100. else
  101. stats_autoadd(m, chan->dname);
  102. #else
  103. if (m->user != NULL)
  104. incrstats(m->user->handle, chan->name, T_MINUTES, 1, 0);
  105. else
  106. stats_autoadd(m, chan->name);
  107. #endif
  108. }
  109. }
  110. }
  111. } else {
  112. for (ch = schans; ch; ch = ch->next) {
  113. if (nostats(ch->chan))
  114. continue;
  115. for (mm = ch->members; mm; mm = mm->next) {
  116. if (mm->user) {
  117. if (!mm->stats)
  118. mm->stats = initstats(ch->chan, mm->user->user);
  119. // now let's use a generic flag to check if we already increased this
  120. // user's minutes (if he's a clone, for example)
  121. // (thanks to Zev for this idea)
  122. if (mm->stats->flag)
  123. continue;
  124. nincrstats(mm->stats, T_MINUTES, 1);
  125. mm->stats->flag = 1;
  126. } else {
  127. stats_autosadd(mm, ch);
  128. }
  129. }
  130. // now reset the flag
  131. for (mm = ch->members; mm; mm = mm->next)
  132. if (mm->stats)
  133. mm->stats->flag = 0;
  134. }
  135. }
  136. Context;
  137. }
  138. static void sensor_countusers()
  139. {
  140. struct chanset_t *chan;
  141. memberlist *m;
  142. struct stats_chanset *ch;
  143. struct stats_memberlist *mm;
  144. globstats *gs;
  145. int hour, nr;
  146. for (chan = chanset; chan; chan = chan->next) {
  147. if (chan->channel.members < 1)
  148. continue;
  149. nr = 0;
  150. #if EGG_IS_MIN_VER(10500)
  151. if (nostats(chan->name))
  152. continue;
  153. gs = findglobstats(chan->dname);
  154. #else
  155. if (nostats(chan->name))
  156. continue;
  157. gs = findglobstats(chan->name);
  158. #endif
  159. if (!gs)
  160. continue;
  161. if (use_userfile) {
  162. for (m = chan->channel.member; m; m = m->next) {
  163. if (!m->nick[0])
  164. continue;
  165. if (m->user != NULL)
  166. #if EGG_IS_MIN_VER(10500)
  167. if (matchattr(m->user, nostatsflags, chan->dname))
  168. #else
  169. if (matchattr(m->user, nostatsflags, chan->name))
  170. #endif
  171. continue;
  172. nr++;
  173. }
  174. } else {
  175. #if EGG_IS_MIN_VER(10500)
  176. ch = findschan(chan->dname);
  177. #else
  178. ch = findschan(chan->name);
  179. #endif
  180. if (!ch)
  181. continue;
  182. for (mm = ch->members; mm; mm = mm->next) {
  183. if (mm->user && !mm->user->list)
  184. continue;
  185. nr++;
  186. }
  187. }
  188. hour = gethour();
  189. if (hour != lasthour) {
  190. gs->users[S_USERSUM][hour] = nr;
  191. gs->users[S_USERCOUNTS][hour] = 1;
  192. lasthour = hour;
  193. } else {
  194. gs->users[S_USERSUM][hour] += nr;
  195. if (gs->users[S_USERCOUNTS][hour] < 0)
  196. gs->users[S_USERCOUNTS][hour] = 1;
  197. else
  198. gs->users[S_USERCOUNTS][hour]++;
  199. }
  200. }
  201. }
  202. static void sensor_peak(char *channel)
  203. {
  204. struct chanset_t *chan;
  205. memberlist *m;
  206. struct stats_chanset *ch;
  207. struct stats_memberlist *mm;
  208. globstats *gs;
  209. int users = 0;
  210. if (nostats(channel))
  211. return;
  212. gs = findglobstats(channel);
  213. if (!gs)
  214. return;
  215. #ifndef OLDBOT
  216. chan = findchan_by_dname(channel);
  217. #else
  218. chan = findchan(channel);
  219. #endif
  220. if (!chan)
  221. return;
  222. if (use_userfile) {
  223. if (chan->channel.members > 0) {
  224. for (m = chan->channel.member; m; m = m->next) {
  225. if (!m->nick[0])
  226. continue;
  227. if (m->user) {
  228. if (matchattr(m->user, nopeak, channel))
  229. continue;
  230. }
  231. users++;
  232. }
  233. }
  234. } else {
  235. #if EGG_IS_MIN_VER(10500)
  236. ch = findschan(chan->dname);
  237. #else
  238. ch = findschan(chan->name);
  239. #endif
  240. if (!ch)
  241. return;
  242. for (mm = ch->members; mm; mm = mm->next) {
  243. if (mm->user && !mm->user->list)
  244. continue;
  245. users++;
  246. }
  247. }
  248. if (users > gs->peak[S_TOTAL]) {
  249. gs->peak[S_TOTAL] = users;
  250. putlog(LOG_MISC, "*", "New user peak in %s: %d.", channel, users);
  251. }
  252. if (users > gs->peak[S_TODAY])
  253. gs->peak[S_TODAY] = users;
  254. if (users > gs->peak[S_WEEKLY])
  255. gs->peak[S_WEEKLY] = users;
  256. if (users > gs->peak[S_MONTHLY])
  257. gs->peak[S_MONTHLY] = users;
  258. }
  259. static int sensor_topc(char *nick, char *uhost, char *hand, char *chan, char *topic)
  260. {
  261. struct stats_memberlist *m;
  262. Context;
  263. if (nostats(chan))
  264. return 0;
  265. if (!use_userfile) {
  266. m = nick2suser(nick, chan);
  267. if (!m)
  268. return 0;
  269. if (!m->user)
  270. return 0;
  271. if (!m->stats)
  272. m->stats = initstats(chan, m->user->user);
  273. nincrstats(m->stats, T_TOPICS, 1);
  274. } else if (hand[0] != '*')
  275. incrstats(hand, chan, T_TOPICS, 1, 0);
  276. addtopic(chan, topic, nick);
  277. return 0;
  278. }
  279. static int sensor_action(char *nick, char *uhost, char *hand, char *chan, char *key, char *rest)
  280. {
  281. char *pbuf;
  282. struct stats_memberlist *m;
  283. if (!strchr(CHANMETA, chan[0]))
  284. return 0;
  285. if (nostats(chan))
  286. return 0;
  287. if (!use_userfile) {
  288. m = nick2suser(nick, chan);
  289. if (!m)
  290. return 0;
  291. if (!m->user)
  292. return 0;
  293. if (!m->stats)
  294. m->stats = initstats(chan, m->user->user);
  295. nincrstats(m->stats, T_ACTIONS, 1);
  296. } else if (hand[0] != '*')
  297. incrstats(hand, chan, T_ACTIONS, 1, 0);
  298. pbuf = nmalloc(strlen(nick) + strlen(rest) + 2);
  299. sprintf(pbuf, "%s %s", nick, rest);
  300. sensor_msgm(nick, uhost, hand, chan, pbuf);
  301. nfree(pbuf);
  302. return 0;
  303. }
  304. static int sensor_kick(char *nick, char *uhost, char *hand, char *chan, char *victim, char *reason)
  305. {
  306. struct stats_memberlist *m;
  307. char *buf;
  308. globstats *gs;
  309. if (nostats(chan))
  310. return 0;
  311. gs = findglobstats(chan);
  312. buf = nmalloc(strlen(victim) + strlen(nick) + strlen(reason) + 23);
  313. sprintf(buf, "*** %s was kicked by %s (%s)", victim, nick, reason);
  314. add_chanlog(gs, nick, buf, SL_KICK);
  315. save_kick(gs, buf);
  316. nfree(buf);
  317. skillmember(chan, victim);
  318. if (!use_userfile) {
  319. m = nick2suser(nick, chan);
  320. if (!m)
  321. return 0;
  322. if (!m->user)
  323. return 0;
  324. if (!m->stats)
  325. m->stats = initstats(chan, m->user->user);
  326. nincrstats(m->stats, T_KICKS, 1);
  327. } else if (hand[0] != '*')
  328. incrstats(hand, chan, T_KICKS, 1, 0);
  329. return 0;
  330. }
  331. static int sensor_mode(char *nick, char *uhost, char *hand, char *chan, char *mode, char *victim)
  332. {
  333. struct stats_memberlist *m;
  334. char *buf;
  335. if (nostats(chan))
  336. return 0;
  337. Assert(mode);
  338. if (mode[1] == 'k')
  339. return 0;
  340. buf = nmalloc(strlen(nick) + strlen(mode) + strlen(victim) + 13);
  341. sprintf(buf, "%s sets mode %s %s", nick, mode, victim);
  342. add_chanlog(findglobstats(chan), nick, buf, SL_MODE);
  343. nfree(buf);
  344. if (!use_userfile) {
  345. m = nick2suser(nick, chan);
  346. if (!m)
  347. return 0;
  348. if (!m->user)
  349. return 0;
  350. if (!m->stats)
  351. m->stats = initstats(chan, m->user->user);
  352. nincrstats(m->stats, T_MODES, 1);
  353. if ((mode[1] == 'b') && (mode[0] == '+'))
  354. nincrstats(m->stats, T_BANS, 1);
  355. } else if (hand[0] != '*') {
  356. incrstats(hand, chan, T_MODES, 1, 0);
  357. if ((mode[1] == 'b') && (mode[0] == '+'))
  358. incrstats(hand, chan, T_BANS, 1, 0);
  359. }
  360. return 0;
  361. }
  362. static int sensor_nick(char *nick, char *uhost, char *hand, char *chan, char *newnick)
  363. {
  364. struct stats_memberlist *m;
  365. if (nostats(chan))
  366. return 0;
  367. add_chanlog(findglobstats(chan), nick, newnick, SL_NICK);
  368. strackmember(chan, nick, newnick);
  369. if (!use_userfile) {
  370. m = nick2suser(newnick, chan);
  371. if (!m)
  372. return 0;
  373. if (!m->user)
  374. return 0;
  375. if (!m->stats)
  376. m->stats = initstats(chan, m->user->user);
  377. nincrstats(m->stats, T_NICKS, 1);
  378. } else if (hand[0] != '*')
  379. incrstats(hand, chan, T_NICKS, 1, 0);
  380. return 0;
  381. }
  382. static int sensor_join(char *nick, char *uhost, char *hand, char *chan)
  383. {
  384. struct stats_memberlist *m;
  385. if (nostats(chan))
  386. return 0;
  387. add_chanlog(findglobstats(chan), nick, NULL, SL_JOIN);
  388. if (match_my_nick(nick))
  389. free_one_chan(chan);
  390. else
  391. saddmember(nick, uhost, hand, chan);
  392. sensor_peak(chan);
  393. if (!use_userfile) {
  394. m = nick2suser(nick, chan);
  395. if (!m)
  396. return 0;
  397. if (!m->user)
  398. return 0;
  399. if (!m->stats)
  400. m->stats = initstats(chan, m->user->user);
  401. nincrstats(m->stats, T_JOINS, 1);
  402. } else if (hand[0] != '*')
  403. incrstats(hand, chan, T_JOINS, 1, 0);
  404. addhost(uhost, findglobstats(chan));
  405. return 0;
  406. }
  407. static int sensor_part(char *nick, char *uhost, char *hand, char *chan)
  408. {
  409. if (nostats(chan))
  410. return 0;
  411. add_chanlog(findglobstats(chan), nick, NULL, SL_PART);
  412. skillmember(chan, nick);
  413. return 0;
  414. }
  415. static int sensor_sign(char *nick, char *uhost, char *hand, char *chan, char *reason)
  416. {
  417. if (nostats(chan))
  418. return 0;
  419. add_chanlog(findglobstats(chan), nick, reason, SL_QUIT);
  420. skillmember(chan, nick);
  421. return 0;
  422. }
  423. static cmd_t stats_pubm[] =
  424. {
  425. {"*", "", (Function) sensor_msgm, "stat"},
  426. {0, 0, 0, 0}
  427. };
  428. static cmd_t stats_topc[] =
  429. {
  430. {"*", "", (Function) sensor_topc, "stat"},
  431. {0, 0, 0, 0}
  432. };
  433. static cmd_t stats_ctcp[] =
  434. {
  435. {"ACTION", "", (Function) sensor_action, "stat"},
  436. {0, 0, 0, 0}
  437. };
  438. static cmd_t stats_kick[] =
  439. {
  440. {"*", "", (Function) sensor_kick, "stat"},
  441. {0, 0, 0, 0}
  442. };
  443. static cmd_t stats_mode[] =
  444. {
  445. {"*", "", (Function) sensor_mode, "stat"},
  446. {0, 0, 0, 0}
  447. };
  448. static cmd_t stats_nick[] =
  449. {
  450. {"*", "", (Function) sensor_nick, "stat"},
  451. {0, 0, 0, 0}
  452. };
  453. static cmd_t stats_join[] =
  454. {
  455. {"*", "", (Function) sensor_join, "stat"},
  456. {0, 0, 0, 0}
  457. };
  458. static cmd_t stats_part[] =
  459. {
  460. {"*", "", (Function) sensor_part, "stat"},
  461. {0, 0, 0, 0}
  462. };
  463. static cmd_t stats_sign[] =
  464. {
  465. {"*", "", (Function) sensor_sign, "stat"},
  466. {0, 0, 0, 0}
  467. };