stats.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. /*
  2. * Statistics module for eggdrop 1.4+
  3. * by G`Quann
  4. */
  5. /*
  6. * stats.c - this is never gonna work... (Oct 99)
  7. */
  8. /*
  9. * oops... seems that it works :) (Dec 99)
  10. */
  11. /*
  12. * Copyright (C) 2000,2001 Florian Sander
  13. *
  14. * This program is free software; you can redistribute it and/or
  15. * modify it under the terms of the GNU General Public License
  16. * as published by the Free Software Foundation; either version 2
  17. * of the License, or (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program; if not, write to the Free Software
  26. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  27. */
  28. #define MAKING_STATS
  29. #define MODULE_NAME "stats"
  30. #define MODULE_VERSION "1.5.0"
  31. #ifndef NO_EGG
  32. #include "../module.h"
  33. #include "../irc.mod/irc.h"
  34. #include "../server.mod/server.h"
  35. #include "../channels.mod/channels.h"
  36. #else
  37. #include "compat/noegg.h"
  38. #include "compat/noegg.c"
  39. #endif
  40. #include <stdlib.h>
  41. #include <sys/stat.h>
  42. #include <time.h> /* for time_t */
  43. #include <ctype.h>
  44. #include <sys/types.h>
  45. #include <fcntl.h>
  46. #undef global
  47. #ifndef NO_EGG
  48. static Function *global = NULL, *irc_funcs = NULL, *server_funcs = NULL, *channels_funcs = NULL;
  49. #endif
  50. #ifndef EGG_IS_MIN_VER
  51. #define EGG_IS_MIN_VER(ver) ((ver) <= 10400)
  52. #endif
  53. #if !EGG_IS_MIN_VER(10500)
  54. #define OLDBOT 1
  55. #endif
  56. #ifndef Context
  57. #define Context context
  58. #endif
  59. #ifndef findchan_by_dname
  60. #define findchan_by_dname findchan
  61. #endif
  62. #ifndef my_htonl
  63. #define my_htonl htonl
  64. #endif
  65. // #include "stats.h"
  66. #ifndef NO_MEM_DEBUG
  67. #ifndef DYNAMIC_MEM_DEBUG
  68. #include "core/dynamic_mem_debug.c"
  69. #endif
  70. #endif
  71. /* static struct slang_lang *slangs = NULL;
  72. static struct slang_chan *slangchans = NULL;
  73. */
  74. #include "egg_chancontrol.h"
  75. #include "core/core.c"
  76. #include "settings.c"
  77. #include "misc.c"
  78. #include "pubcmds.h"
  79. #include "pubcmds.c"
  80. #include "msgcmds.c"
  81. #include "dcccmds.h"
  82. #include "dcccmds.c"
  83. #include "tclstats.c"
  84. #include "egg_chancontrol.c"
  85. #include "egg_bindings.c"
  86. static int stats_save_temp = 1;
  87. static int stats_expmem()
  88. {
  89. return 0;
  90. }
  91. /*
  92. static int stats_expmem()
  93. {
  94. int size = 0;
  95. Context;
  96. #ifdef DYNAMIC_MEM_DEBUG
  97. return 0;
  98. #endif
  99. size += stats_globstats_expmem(sdata);
  100. Context;
  101. size += suserlist_expmem(suserlist);
  102. size += llist_expmem(&schanset);
  103. size += expmem_templates();
  104. size += expmem_httpd();
  105. size += expmem_global_vars();
  106. size += slang_glob_expmem();
  107. size += slang_expmem(coreslangs);
  108. size += slang_chanlang_expmem(chanlangs);
  109. if (stats_pubcmd_reply)
  110. size += strlen(stats_pubcmd_reply) + 1;
  111. return size;
  112. }
  113. static int stats_globstats_expmem(struct stats_global *gs)
  114. {
  115. int size = 0;
  116. while (gs) {
  117. size += sizeof(struct stats_global);
  118. size += strlen(gs->chan) + 1;
  119. size += localstats_expmem(gs->local);
  120. size += wordstats_expmem(gs->words);
  121. size += topics_expmem(gs->topics);
  122. size += urls_expmem(gs->urls);
  123. size += hosts_expmem(gs->hosts);
  124. size += quotes_expmem(gs->log);
  125. size += kicks_expmem(gs->kicks);
  126. gs = gs->next;
  127. }
  128. return size;
  129. }
  130. static int suserlist_expmem(struct stats_userlist *e)
  131. {
  132. int size = 0;
  133. Context;
  134. while (e) {
  135. size += stats_userlist_expmem_entry(e);
  136. e = e->next;
  137. }
  138. return size;
  139. }
  140. static int hostlist_expmem(struct stats_hostlist *e)
  141. {
  142. int size = 0;
  143. Context;
  144. while (e) {
  145. size += sizeof(struct stats_hostlist);
  146. size += strlen(e->mask) + 1;
  147. e = e->next;
  148. }
  149. return size;
  150. }
  151. static int localstats_expmem(struct stats_local *sl)
  152. {
  153. int size = 0;
  154. Context;
  155. while (sl) {
  156. size += sizeof(struct stats_local);
  157. size += strlen(sl->user) + 1;
  158. size += wordstats_expmem(sl->words);
  159. size += quotes_expmem(sl->quotes);
  160. sl = sl->next;
  161. }
  162. Context;
  163. return size;
  164. }
  165. static int wordstats_expmem(wordstats *l)
  166. {
  167. int size = 0;
  168. Context;
  169. while (l) {
  170. size += strlen(l->word) + 1;
  171. size += sizeof(wordstats);
  172. l = l->next;
  173. }
  174. return size;
  175. }
  176. static int quotes_expmem(quotestr *l)
  177. {
  178. int size = 0;
  179. Context;
  180. while (l) {
  181. size += strlen(l->quote) + 1;
  182. size += sizeof(quotestr);
  183. l = l->next;
  184. }
  185. return size;
  186. }
  187. static int topics_expmem(topicstr *e)
  188. {
  189. int size = 0;
  190. Context;
  191. while (e) {
  192. size += strlen(e->topic) + 1;
  193. size += strlen(e->by) + 1;
  194. size += sizeof(topicstr);
  195. e = e->next;
  196. }
  197. return size;
  198. }
  199. static int urls_expmem(struct stats_url *e)
  200. {
  201. int size = 0;
  202. Context;
  203. while (e) {
  204. size += strlen(e->url) + 1;
  205. size += strlen(e->by) + 1;
  206. size += sizeof(struct stats_url);
  207. e = e->next;
  208. }
  209. return size;
  210. }
  211. static int kicks_expmem(struct stats_kick *e)
  212. {
  213. int size = 0;
  214. Context;
  215. while (e) {
  216. size += sizeof(struct stats_kick);
  217. size += quotes_expmem(e->log);
  218. e = e->next;
  219. }
  220. return size;
  221. }
  222. static int hosts_expmem(hoststr *e)
  223. {
  224. int size = 0;
  225. Context;
  226. while (e) {
  227. size += strlen(e->host) + 1;
  228. size += sizeof(hoststr);
  229. e = e->next;
  230. }
  231. return size;
  232. }
  233. */
  234. /* a report on the module status */
  235. static void stats_report(int idx, int details)
  236. {
  237. // int memtotal, memusers, memchans, memtemplates, memslang, memdata;
  238. int users, hosts;
  239. Context;
  240. users = countsusers();
  241. hosts = counthosts();
  242. if (!details)
  243. dprintf(idx, " Stats-userbase contains %d users and %d hosts\n", users, hosts);
  244. else {
  245. /* memtotal = stats_expmem();
  246. memdata = stats_globstats_expmem(sdata);
  247. memusers = suserlist_expmem(suserlist);
  248. memchans = llist_expmem(&schanset);
  249. memtemplates = expmem_templates();
  250. memslang = slang_glob_expmem() + slang_expmem(coreslangs) +
  251. slang_chanlang_expmem(chanlangs);
  252. dprintf(idx, " Stats-userbase contains %d users and %d hosts using "
  253. "%d bytes.\n", users, hosts, memusers);
  254. dprintf(idx, " Statistic data itself using %d bytes.\n", memdata);
  255. dprintf(idx, " Channels and channel members using %d bytes.\n", memchans);
  256. dprintf(idx, " Templates using %d bytes.\n", memtemplates);
  257. dprintf(idx, " Total memory usage: %d bytes.\n", memtotal); */
  258. }
  259. }
  260. static void stats_minutely ()
  261. {
  262. eggbnd_minutely();
  263. if (stats_save_temp >= stats_save_time) {
  264. write_stats();
  265. stats_save_temp = 1;
  266. } else
  267. stats_save_temp++;
  268. }
  269. static void stats_daily ()
  270. {
  271. Context;
  272. deloldstatusers();
  273. purgestats();
  274. reset_tstats();
  275. if (lastmonth != getmonth()) {
  276. reset_mwstats(S_MONTHLY);
  277. lastmonth = getmonth();
  278. }
  279. if (ismonday())
  280. reset_mwstats(S_WEEKLY);
  281. update_schannel_members();
  282. Context;
  283. }
  284. static tcl_ints my_tcl_ints[] =
  285. {
  286. {"save-stats", &stats_save_time, 0},
  287. {"webnr", &webnr, 0},
  288. {"topnr", &webnr, 0},
  289. {"graphnr", &graphnr, 0},
  290. {"autoadd", &autoadd, 0},
  291. {"write-today", &write_today, 0},
  292. {"stats-file-mode", &statsfilemode, 0},
  293. {"livestats-timeout", &livestats_timeout, 0},
  294. {"offset", &offset, 0},
  295. {"topwords-limit", &topwords_limit, 0},
  296. {"quote-frequency", &quote_freq, 0},
  297. {"log-wordstats", &log_wordstats, 0},
  298. {"min-word-length", &min_word_length, 0},
  299. {"table-color", &table_color, 0},
  300. {"fade-table-to", &fade_table_to, 0},
  301. {"table-border", &table_border, 0},
  302. {"display-urls", &log_urls, 0},
  303. {"kick-context", &kick_context, 0},
  304. {"display-kicks", &display_kicks, 0},
  305. {"display-average-users", &display_average_users, 0},
  306. {"show-userlist", &show_userlist, 0},
  307. {"show-usersonchan", &show_usersonchan, 0},
  308. {"list-secret-chans", &list_secret_chans, 0},
  309. {"autoadd-min-lines", &autoadd_min_lines, 0},
  310. {"min-lines", &min_lines, 0},
  311. {"expire-base", &expire_base, 0},
  312. {"expire-factor", &expire_factor, 0},
  313. {0, 0, 0}
  314. };
  315. static tcl_strings my_tcl_strings[] =
  316. {
  317. {"statsfile", statsfile, 121, 0},
  318. {"webstats", webstats, 510, 0},
  319. {"topstats", webstats, 510, 0},
  320. {"webdir", webdir, 256, 0},
  321. {"smileys", smileys, 128, 0},
  322. {"smilies", smileys, 128, 0},
  323. {"graphstats", graphstats, 510, 0},
  324. {"graphgif", graphgif, 128, 0},
  325. {"graphcolor", graphcolor, 20, 0},
  326. {"anti-autoadd-flags", badflags, 20, 0},
  327. {"anti-stats-flag", nostatsflags, 20, 0},
  328. {"anti-peak-flag", nopeak, 20, 0},
  329. {"network", network, 40, 0},
  330. {"livestats-loglevel", httpd_loglevel, 20, 0},
  331. {"livestats-log", httpd_log, 121, 0},
  332. {"stat-reply", stat_reply, 128, 0},
  333. {"livestats-ignore-msg", httpd_ignore_msg, 255, 0},
  334. {"livestats-ip", httpd_ip, 20, 0},
  335. {"default-slang", default_slang, 20, 0},
  336. {"default-skin", default_skin, 20, 0},
  337. {"binary-url", binary_url, 120, 0},
  338. {0, 0, 0, 0}
  339. };
  340. static tcl_coups my_tcl_coups[] =
  341. {
  342. {"max-stat-cmds", &maxstat_thr, &maxstat_time},
  343. {"max-livestats-access", &maxlivestats_thr, &maxlivestats_time},
  344. {0, 0, 0},
  345. };
  346. static char *stats_close()
  347. {
  348. Context;
  349. stats_core_unload();
  350. unload_httpd();
  351. unload_templates();
  352. write_stats();
  353. free_stats();
  354. free_global_vars();
  355. slang_chanlang_free(chanlangs);
  356. if (stats_pubcmd_reply)
  357. nfree(stats_pubcmd_reply);
  358. rem_builtins(H_dcc, mydcc);
  359. rem_builtins(H_pubm, stats_pubm);
  360. rem_builtins(H_pub, stats_pub);
  361. rem_builtins(H_msg, stats_msg);
  362. rem_builtins(H_topc, stats_topc);
  363. rem_builtins(H_ctcp, stats_ctcp);
  364. rem_builtins(H_kick, stats_kick);
  365. rem_builtins(H_mode, stats_mode);
  366. rem_builtins(H_nick, stats_nick);
  367. rem_builtins(H_join, stats_join);
  368. rem_builtins(H_nkch, stats_nkch);
  369. rem_builtins(H_sign, stats_sign);
  370. rem_builtins(H_part, stats_part);
  371. rem_tcl_ints(my_tcl_ints);
  372. rem_tcl_coups(my_tcl_coups);
  373. rem_tcl_strings(my_tcl_strings);
  374. rem_tcl_commands(mytcls);
  375. rem_help_reference("stats.help");
  376. del_hook(HOOK_MINUTELY, (Function) stats_minutely);
  377. del_hook(HOOK_DAILY, (Function) stats_daily);
  378. module_undepend(MODULE_NAME);
  379. #ifndef NO_MEM_DEBUG
  380. dmd_unload();
  381. #endif
  382. return NULL;
  383. }
  384. char *stats_start();
  385. static Function stats_table[] =
  386. {
  387. (Function) stats_start,
  388. (Function) stats_close,
  389. (Function) stats_expmem,
  390. (Function) stats_report,
  391. };
  392. char *stats_start(Function * global_funcs)
  393. {
  394. global = global_funcs;
  395. Context;
  396. #ifndef NO_MEM_DEBUG
  397. dmd_init();
  398. #endif
  399. stats_core_init();
  400. // schans = NULL;
  401. suserlist = NULL;
  402. // slangs = NULL;
  403. // slangchans = NULL;
  404. stats_pubcmd_reply = NULL;
  405. chanlangs = NULL;
  406. slang_glob_init();
  407. Context;
  408. module_register(MODULE_NAME, stats_table, 1, 5);
  409. if (!(irc_funcs = module_depend(MODULE_NAME, "irc", 1, 0)))
  410. return "You need the irc module to use the stats module.";
  411. if (!(server_funcs = module_depend(MODULE_NAME, "server", 1, 0)))
  412. return "You need the server module to use the stats module.";
  413. if (!(channels_funcs = module_depend(MODULE_NAME, "channels", 1, 0)))
  414. return "You need the channels module to use the stats module.";
  415. if (!module_depend(MODULE_NAME, "eggdrop", 108, 0)) {
  416. module_undepend(MODULE_NAME);
  417. return "Sorry, stats.mod requires Eggdrop 1.8.0 or later.";
  418. }
  419. #ifndef OLDBOT
  420. livestats_timeout = 10;
  421. #else
  422. livestats_timeout = 1;
  423. #endif
  424. add_builtins(H_dcc, mydcc);
  425. add_builtins(H_pubm, stats_pubm);
  426. add_builtins(H_pub, stats_pub);
  427. add_builtins(H_msg, stats_msg);
  428. add_builtins(H_topc, stats_topc);
  429. add_builtins(H_ctcp, stats_ctcp);
  430. add_builtins(H_kick, stats_kick);
  431. add_builtins(H_mode, stats_mode);
  432. add_builtins(H_nick, stats_nick);
  433. add_builtins(H_join, stats_join);
  434. add_builtins(H_nkch, stats_nkch);
  435. add_builtins(H_sign, stats_sign);
  436. add_builtins(H_part, stats_part);
  437. add_tcl_ints(my_tcl_ints);
  438. add_tcl_coups(my_tcl_coups);
  439. add_tcl_strings(my_tcl_strings);
  440. add_tcl_commands(mytcls);
  441. add_hook(HOOK_MINUTELY, (Function) stats_minutely);
  442. add_hook(HOOK_DAILY, (Function) stats_daily);
  443. add_help_reference("stats.help");
  444. lastmonth = getmonth();
  445. read_stats();
  446. #if EGG_IS_MIN_VER(10503)
  447. initudef(1, "nopubstats", 1);
  448. initudef(1, "quietstats", 1);
  449. initudef(1, "nostats", 1);
  450. #endif
  451. init_httpd();
  452. init_templates();
  453. init_global_vars();
  454. glob_tpl_cmd_list = templates_commands_list_add(glob_tpl_cmd_list, stats_template_commands);
  455. glob_tpl_cmd_list = templates_commands_list_add(glob_tpl_cmd_list, template_httpd_commands);
  456. glob_slang_cmd_list = slang_commands_list_add(glob_slang_cmd_list, slang_text_stats_command_table);
  457. putlog(LOG_MISC, "*", "Stats.mod v%s loaded.", MODULE_VERSION);
  458. return NULL;
  459. }