00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 #define MODULE_NAME "seen"
00074 #define MAKING_SEEN
00075
00076 #include "src/mod/module.h"
00077
00078 #ifdef TIME_WITH_SYS_TIME
00079 # include <sys/time.h>
00080 # include <time.h>
00081 #else
00082 # ifdef HAVE_SYS_TIME_H
00083 # include <sys/time.h>
00084 # else
00085 # include <time.h>
00086 # endif
00087 #endif
00088
00089 #include "src/users.h"
00090 #include "src/chan.h"
00091 #include "channels.mod/channels.h"
00092
00093 static Function *global = NULL;
00094 static void wordshift();
00095 static void do_seen();
00096 static char *match_trigger();
00097 static char *getxtra();
00098 static char *fixnick();
00099
00100 typedef struct {
00101 char *key;
00102 char *text;
00103 } trig_data;
00104
00105 static trig_data trigdata[] = {
00106 {"god", "Let's not get into a religious discussion, %s"},
00107 {"jesus", "Let's not get into a religious discussion, %s"},
00108 {"shit", "Here's looking at you, %s"},
00109 {"yourself", "Yeah, whenever I look in a mirror..."},
00110 {NULL, " You found me, %s!"},
00111 {"elvis", "Last time I was on the moon man."},
00112 {NULL, NULL}
00113 };
00114
00115 static int seen_expmem()
00116 {
00117 return 0;
00118 }
00119
00120
00121 static int pub_seen(char *nick, char *host, char *hand,
00122 char *channel, char *text)
00123 {
00124 char prefix[91];
00125 struct chanset_t *chan = findchan_by_dname(channel);
00126
00127 if ((chan != NULL) && channel_seen(chan)) {
00128 egg_snprintf(prefix, sizeof prefix, "PRIVMSG %s :", chan->name);
00129 do_seen(DP_HELP, prefix, nick, hand, chan->dname, text);
00130 }
00131 return 0;
00132 }
00133
00134 static int msg_seen(char *nick, char *host, struct userrec *u, char *text)
00135 {
00136 char prefix[50];
00137
00138 if (!u) {
00139 putlog(LOG_CMDS, "*", "[%s!%s] seen %s", nick, host, text);
00140 return 0;
00141 }
00142 putlog(LOG_CMDS, "*", "(%s!%s) !%s! SEEN %s", nick, host, u->handle, text);
00143 sprintf(prefix, "PRIVMSG %s :", nick);
00144 do_seen(DP_SERVER, prefix, nick, u->handle, "", text);
00145 return 0;
00146 }
00147
00148 static int dcc_seen(struct userrec *u, int idx, char *par)
00149 {
00150 putlog(LOG_CMDS, "*", "#%s# seen %s", dcc[idx].nick, par);
00151 do_seen(idx, "", dcc[idx].nick, dcc[idx].nick, "", par);
00152 return 0;
00153 }
00154
00155 static void do_seen(int idx, char *prefix, char *nick, char *hand,
00156 char *channel, char *text)
00157 {
00158 char stuff[512], word1[512], word2[512], whotarget[512], object[512],
00159 whoredirect[512], *oix, *lastonplace = 0;
00160 struct userrec *urec;
00161 struct chanset_t *chan;
00162 struct laston_info *li;
00163 struct chanuserrec *cr;
00164 memberlist *m = NULL;
00165 int onchan = 0, i;
00166 long tv;
00167 time_t laston = 0, work;
00168
00169 whotarget[0] = 0;
00170 whoredirect[0] = 0;
00171 object[0] = 0;
00172
00173
00174 if (!text[0]) {
00175 dprintf(idx, "%sUm, %s, it might help if you ask me about _someone_...\n",
00176 prefix, nick);
00177 return;
00178 }
00179
00180 wordshift(word1, text);
00181 oix = strchr(word1, '\'');
00182
00183 if (oix == word1)
00184 return;
00185 if (oix && *oix && ((oix[1] && (oix[1] == 's' || oix[1] == 'S') &&
00186 !oix[2]) || (!oix[1] && (oix[-1] == 's' || oix[-1] == 'z' ||
00187 oix[-1] == 'x' || oix[-1] == 'S' || oix[-1] == 'Z' ||
00188 oix[-1] == 'X')))) {
00189 strncpy(object, word1, oix - word1);
00190 object[oix - word1] = 0;
00191 wordshift(word1, text);
00192 if (!word1[0]) {
00193 dprintf(idx, "%s%s's what, %s?\n", prefix, object, nick);
00194 return;
00195 }
00196 urec = get_user_by_handle(userlist, object);
00197 if (!urec) {
00198 chan = chanset;
00199 while (chan) {
00200 onchan = 0;
00201 m = ismember(chan, object);
00202 if (m) {
00203 onchan = 1;
00204 sprintf(stuff, "%s!%s", object, m->userhost);
00205 urec = get_user_by_host(stuff);
00206 if (!urec || !egg_strcasecmp(object, urec->handle))
00207 break;
00208 strcat(whoredirect, object);
00209 strcat(whoredirect, " is ");
00210 strcat(whoredirect, urec->handle);
00211 strcat(whoredirect, ", and ");
00212 strcpy(object, urec->handle);
00213 break;
00214 }
00215 chan = chan->next;
00216 }
00217 if (!onchan) {
00218 dprintf(idx, "%sI don't think I know who %s is, %s.\n",
00219 prefix, object, nick);
00220 return;
00221 }
00222 }
00223 if (!egg_strcasecmp(word1, "bf") || !egg_strcasecmp(word1, "boyfriend")) {
00224 strcpy(whotarget, getxtra(object, "BF"));
00225 if (whotarget[0]) {
00226 sprintf(whoredirect, "%s boyfriend is %s, and ",
00227 fixnick(object), whotarget);
00228 goto targetcont;
00229 }
00230 dprintf(idx,
00231 "%sI don't know who %s boyfriend is, %s.\n",
00232 prefix, fixnick(object), nick);
00233 return;
00234 }
00235 if (!egg_strcasecmp(word1, "gf") || !egg_strcasecmp(word1, "girlfriend")) {
00236 strcpy(whotarget, getxtra(object, "GF"));
00237 if (whotarget[0]) {
00238 sprintf(whoredirect, "%s girlfriend is %s, and ",
00239 fixnick(object), whotarget);
00240 goto targetcont;
00241 }
00242 dprintf(idx,
00243 "%sI don't know who %s girlfriend is, %s.\n",
00244 prefix, fixnick(object), nick);
00245 return;
00246 }
00247 dprintf(idx,
00248 "%sWhy are you bothering me with questions about %s %s, %s?\n",
00249 prefix, fixnick(object), word1, nick);
00250 return;
00251 }
00252
00253 if (!egg_strcasecmp(word1, "my")) {
00254 wordshift(word1, text);
00255 if (!word1[0]) {
00256 dprintf(idx, "%sYour what, %s?\n", prefix, nick);
00257 return;
00258 }
00259
00260 if (hand[0] == '*' || !hand[0]) {
00261 dprintf(idx,
00262 "%sI don't know you, %s, so I don't know about your %s.\n",
00263 prefix, nick, word1);
00264 return;
00265 }
00266
00267 if (!egg_strcasecmp(word1, "boyfriend") || !egg_strcasecmp(word1, "bf")) {
00268 strcpy(whotarget, getxtra(hand, "BF"));
00269 if (whotarget[0]) {
00270 sprintf(whoredirect, "%s, your boyfriend is %s, and ", nick, whotarget);
00271 } else {
00272 dprintf(idx, "%sI didn't know you had a boyfriend, %s\n", prefix, nick);
00273 return;
00274 }
00275 }
00276
00277 else if (!egg_strcasecmp(word1, "girlfriend") ||
00278 !egg_strcasecmp(word1, "gf")) {
00279 strcpy(whotarget, getxtra(hand, "GF"));
00280 if (whotarget[0]) {
00281 sprintf(whoredirect, "%s, your girlfriend is %s, and ",
00282 nick, whotarget);
00283 } else {
00284 dprintf(idx, "%sI didn't know you had a girlfriend, %s\n", prefix,
00285 nick);
00286 return;
00287 }
00288 } else {
00289 dprintf(idx, "%sI don't know anything about your %s, %s.\n", prefix,
00290 word1, nick);
00291 return;
00292 }
00293 }
00294
00295 else if (!egg_strcasecmp(word1, "your")) {
00296 wordshift(word1, text);
00297
00298 if (!egg_strcasecmp(word1, "owner") || !egg_strcasecmp(word1, "admin")) {
00299 if (admin[0]) {
00300 strcpy(word2, admin);
00301 wordshift(whotarget, word2);
00302 strcat(whoredirect, "My owner is ");
00303 strcat(whoredirect, whotarget);
00304 strcat(whoredirect, ", and ");
00305 if (!egg_strcasecmp(whotarget, hand)) {
00306 strcat(whoredirect, "that's YOU");
00307 if (!egg_strcasecmp(hand, nick))
00308 strcat(whoredirect, "!!!");
00309 else {
00310 strcat(whoredirect, ", ");
00311 strcat(whoredirect, nick);
00312 strcat(whoredirect, "!");
00313 }
00314 dprintf(idx, "%s%s\n", prefix, whoredirect);
00315 return;
00316 }
00317 } else {
00318 dprintf(idx,
00319 "%sI don't seem to recall who my owner is right now...\n",
00320 prefix);
00321 return;
00322 }
00323 } else {
00324 dprintf(idx, "%sLet's not get personal, %s.\n", prefix, nick);
00325 return;
00326 }
00327 }
00328
00329 else if (match_trigger(word1)) {
00330 sprintf(word2, "%s%s\n", prefix, match_trigger(word1));
00331 dprintf(idx, word2, nick);
00332 return;
00333 }
00334
00335 else
00336 strcpy(whotarget, word1);
00337
00338 targetcont:
00339
00340 if (!rfc_casecmp(nick, whotarget)) {
00341 dprintf(idx, "%s%sLooking for yourself, eh %s?\n",
00342 prefix, whoredirect, nick);
00343 return;
00344 }
00345
00346 chan = chanset;
00347 while (chan) {
00348 m = ismember(chan, whotarget);
00349 if (m) {
00350 onchan = 1;
00351 sprintf(word1, "%s!%s", whotarget, m->userhost);
00352 urec = get_user_by_host(word1);
00353 if (!urec || !egg_strcasecmp(whotarget, urec->handle))
00354 break;
00355 strcat(whoredirect, whotarget);
00356 strcat(whoredirect, " is ");
00357 strcat(whoredirect, urec->handle);
00358 strcat(whoredirect, ", and ");
00359 break;
00360 }
00361 chan = chan->next;
00362 }
00363
00364 if (!onchan) {
00365 chan = chanset;
00366 while (chan) {
00367 m = chan->channel.member;
00368 while (m && m->nick[0]) {
00369 sprintf(word2, "%s!%s", m->nick, m->userhost);
00370 urec = get_user_by_host(word2);
00371 if (urec && !egg_strcasecmp(urec->handle, whotarget)) {
00372 onchan = 1;
00373 strcat(whoredirect, whotarget);
00374 strcat(whoredirect, " is ");
00375 strcat(whoredirect, m->nick);
00376 strcat(whoredirect, ", and ");
00377 strcpy(whotarget, m->nick);
00378 break;
00379 }
00380 m = m->next;
00381 }
00382 chan = chan->next;
00383 }
00384 }
00385
00386 chan = findchan_by_dname(channel);
00387 if (chan) {
00388 m = ismember(chan, whotarget);
00389 if (m && chan_issplit(m)) {
00390 dprintf(idx, "%s%s%s was just here, but got netsplit.\n",
00391 prefix, whoredirect, whotarget);
00392 return;
00393 }
00394 }
00395
00396 if (chan && m) {
00397 dprintf(idx, "%s%s%s is on the channel right now!\n",
00398 prefix, whoredirect, whotarget);
00399 return;
00400 }
00401
00402 chan = chanset;
00403 while (chan) {
00404 m = ismember(chan, whotarget);
00405 if (m && chan_issplit(m)) {
00406 dprintf(idx,
00407 "%s%s%s was just on %s, but got netsplit.\n",
00408 prefix, whoredirect, whotarget, chan->dname);
00409 return;
00410 }
00411 if (m) {
00412 dprintf(idx,
00413 "%s%s%s is on %s right now!\n",
00414 prefix, whoredirect, whotarget, chan->dname);
00415 return;
00416 }
00417 chan = chan->next;
00418 }
00419
00420
00421 urec = get_user_by_handle(userlist, whotarget);
00422
00423 if (!urec) {
00424 dprintf(idx, "%s%sI don't know who %s is.\n",
00425 prefix, whoredirect, whotarget);
00426 return;
00427 }
00428
00429
00430 for (i = 0; i < dcc_total; i++) {
00431 if (dcc[i].type->flags & DCT_CHAT) {
00432 if (!egg_strcasecmp(whotarget, dcc[i].nick)) {
00433 if (!rfc_casecmp(channel, dcc[i].u.chat->con_chan) &&
00434 dcc[i].u.chat->con_flags & LOG_PUBLIC) {
00435 strcat(whoredirect, whotarget);
00436 strcat(whoredirect,
00437 " is 'observing' this channel right now from my party line!");
00438 dprintf(idx, "%s%s\n", prefix, whoredirect);
00439 } else {
00440 dprintf(idx,
00441 "%s%s%s is linked to me via DCC CHAT right now!\n",
00442 prefix, whoredirect, whotarget);
00443 }
00444 return;
00445 }
00446 }
00447 }
00448
00449 wordshift(word1, text);
00450 if (!egg_strcasecmp(word1, "anywhere"))
00451 cr = NULL;
00452 else
00453 for (cr = urec->chanrec; cr; cr = cr->next) {
00454 if (!rfc_casecmp(cr->channel, channel)) {
00455 if (cr->laston) {
00456 laston = cr->laston;
00457 lastonplace = channel;
00458 break;
00459 }
00460 }
00461 }
00462 if (!cr) {
00463 li = get_user(&USERENTRY_LASTON, urec);
00464 if (!li || !li->lastonplace || !li->lastonplace[0]) {
00465 dprintf(idx, "%s%sI've never seen %s around.\n",
00466 prefix, whoredirect, whotarget);
00467 return;
00468 }
00469 lastonplace = li->lastonplace;
00470 laston = li->laston;
00471 }
00472 word1[0] = 0;
00473 word2[0] = 0;
00474 work = now - laston;
00475 if (work >= 86400) {
00476 tv = work / 86400;
00477 sprintf(word2, "%lu day%s, ", tv, (tv == 1) ? "" : "s");
00478 work = work % 86400;
00479 }
00480 if (work >= 3600) {
00481 tv = work / 3600;
00482 sprintf(word2 + strlen(word2), "%lu hour%s, ", tv, (tv == 1) ? "" : "s");
00483 work = work % 3600;
00484 }
00485 if (work >= 60) {
00486 tv = work / 60;
00487 sprintf(word2 + strlen(word2), "%lu minute%s, ", tv,
00488 (tv == 1) ? "" : "s");
00489 }
00490 if (!word2[0] && (work < 60)) {
00491 strcpy(word2, "just moments ago!!");
00492 } else {
00493 strcpy(word2 + strlen(word2) - 2, " ago.");
00494 }
00495 if (lastonplace[0] && (strchr(CHANMETA, lastonplace[0]) != NULL))
00496 sprintf(word1, "on IRC channel %s", lastonplace);
00497 else if (lastonplace[0] == '@')
00498 sprintf(word1, "on %s", lastonplace + 1);
00499 else if (lastonplace[0] != 0)
00500 sprintf(word1, "on my %s", lastonplace);
00501 else
00502 strcpy(word1, "seen");
00503 dprintf(idx, "%s%s%s was last %s %s\n",
00504 prefix, whoredirect, whotarget, word1, word2);
00505 }
00506
00507 static char fixit[512];
00508 static char *fixnick(char *nick)
00509 {
00510 strcpy(fixit, nick);
00511 strcat(fixit, "'");
00512 switch (nick[strlen(nick) - 1]) {
00513 case 's':
00514 case 'S':
00515 case 'x':
00516 case 'X':
00517 case 'z':
00518 case 'Z':
00519 break;
00520 default:
00521 strcat(fixit, "s");
00522 break;
00523 }
00524 return fixit;
00525 }
00526
00527 static char *match_trigger(char *word)
00528 {
00529 trig_data *t = trigdata;
00530
00531 while (t->key) {
00532 if (!egg_strcasecmp(word, t->key))
00533 return t->text;
00534 t++;
00535 }
00536 return (char *) NULL;
00537 }
00538
00539 static char *getxtra(char *hand, char *field)
00540 {
00541
00542 struct userrec *urec;
00543 struct user_entry *ue;
00544 struct xtra_key *xk;
00545
00546 urec = get_user_by_handle(userlist, hand);
00547 if (urec) {
00548 ue = find_user_entry(&USERENTRY_XTRA, urec);
00549 if (ue)
00550 for (xk = ue->u.extra; xk; xk = xk->next)
00551 if (xk->key && !egg_strcasecmp(xk->key, field)) {
00552 if (xk->data[0] == '{' && xk->data[strlen(xk->data) - 1] == '}' &&
00553 strlen(xk->data) > 2) {
00554 strncpy(fixit, &xk->data[1], strlen(xk->data) - 2);
00555 fixit[strlen(xk->data) - 2] = 0;
00556 return fixit;
00557 } else {
00558 return xk->data;
00559 }
00560 }
00561 }
00562 return "";
00563 }
00564
00565 static void wordshift(char *first, char *rest)
00566 {
00567 char *p, *q = rest;
00568
00569 do {
00570 p = newsplit(&q);
00571 strcpy(first, p);
00572 strcpy(rest, q);
00573 } while (!egg_strcasecmp(first, "and") || !egg_strcasecmp(first, "or"));
00574 }
00575
00576
00577 static void seen_report(int idx, int details)
00578 {
00579 if (details) {
00580 int size = seen_expmem();
00581
00582 dprintf(idx, " Using %d byte%s of memory\n", size,
00583 (size != 1) ? "s" : "");
00584 }
00585 }
00586
00587
00588 static cmd_t seen_pub[] = {
00589 {"seen", "", pub_seen, NULL},
00590 {NULL, NULL, NULL, NULL}
00591 };
00592
00593 static cmd_t seen_dcc[] = {
00594 {"seen", "", dcc_seen, NULL},
00595 {NULL, NULL, NULL, NULL}
00596 };
00597
00598 static cmd_t seen_msg[] = {
00599 {"seen", "", msg_seen, NULL},
00600 {NULL, NULL, NULL, NULL}
00601 };
00602
00603 static int server_seen_setup(char *mod)
00604 {
00605 p_tcl_bind_list H_temp;
00606
00607 if ((H_temp = find_bind_table("msg")))
00608 add_builtins(H_temp, seen_msg);
00609 return 0;
00610 }
00611
00612 static int irc_seen_setup(char *mod)
00613 {
00614 p_tcl_bind_list H_temp;
00615
00616 if ((H_temp = find_bind_table("pub")))
00617 add_builtins(H_temp, seen_pub);
00618 return 0;
00619 }
00620
00621 static cmd_t seen_load[] = {
00622 {"server", "", server_seen_setup, NULL},
00623 {"irc", "", irc_seen_setup, NULL},
00624 {NULL, NULL, NULL, NULL}
00625 };
00626
00627 static char *seen_close()
00628 {
00629 p_tcl_bind_list H_temp;
00630
00631 rem_builtins(H_load, seen_load);
00632 rem_builtins(H_dcc, seen_dcc);
00633 rem_help_reference("seen.help");
00634 if ((H_temp = find_bind_table("pub")))
00635 rem_builtins(H_temp, seen_pub);
00636 if ((H_temp = find_bind_table("msg")))
00637 rem_builtins(H_temp, seen_msg);
00638 module_undepend(MODULE_NAME);
00639 return NULL;
00640 }
00641
00642 EXPORT_SCOPE char *seen_start();
00643
00644 static Function seen_table[] = {
00645 (Function) seen_start,
00646 (Function) seen_close,
00647 (Function) seen_expmem,
00648 (Function) seen_report,
00649 };
00650
00651 char *seen_start(Function *egg_func_table)
00652 {
00653 global = egg_func_table;
00654
00655 module_register(MODULE_NAME, seen_table, 2, 0);
00656 if (!module_depend(MODULE_NAME, "eggdrop", 106, 0)) {
00657 module_undepend(MODULE_NAME);
00658 return "This module requires Eggdrop 1.6.0 or later.";
00659 }
00660 add_builtins(H_load, seen_load);
00661 add_builtins(H_dcc, seen_dcc);
00662 add_help_reference("seen.help");
00663 server_seen_setup(NULL);
00664 irc_seen_setup(NULL);
00665 trigdata[4].key = botnetnick;
00666 return NULL;
00667 }