channels.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953
  1. /*
  2. * channels.c -- part of channels.mod
  3. * support for channels within the bot
  4. *
  5. */
  6. #define MAKING_CHANNELS
  7. #include "src/common.h"
  8. #include "src/mod/share.mod/share.h"
  9. #ifdef LEAF
  10. #include "src/mod/irc.mod/irc.h"
  11. #include "src/mod/server.mod/server.h"
  12. #endif /* LEAF */
  13. #include "src/chanprog.h"
  14. #include "src/egg_timer.h"
  15. #include "src/misc.h"
  16. #include "src/main.h"
  17. #include "src/color.h"
  18. #include "src/userrec.h"
  19. #include "src/users.h"
  20. #include "src/cfg.h"
  21. #include "src/rfc1459.h"
  22. #include "src/match.h"
  23. #include "src/settings.h"
  24. #include "src/tandem.h"
  25. #include "src/botnet.h"
  26. #include "src/botmsg.h"
  27. #include "src/net.h"
  28. #include "src/tclhash.h"
  29. #include "src/cmds.h"
  30. #include <sys/stat.h>
  31. static int use_info;
  32. static char glob_chanmode[64]; /* Default chanmode (drummer,990731) */
  33. static int global_stopnethack_mode;
  34. static int global_revenge_mode;
  35. static int global_idle_kick; /* Default idle-kick setting. */
  36. static int global_ban_time;
  37. static int global_exempt_time;
  38. static int global_invite_time;
  39. /* Global channel settings (drummer/dw) */
  40. char glob_chanset[512] = "", cfg_glob_chanset[512] = "";
  41. static char *lastdeletedmask = NULL;
  42. /* Global flood settings */
  43. static int gfld_chan_thr;
  44. static int gfld_chan_time;
  45. static int gfld_deop_thr;
  46. static int gfld_deop_time;
  47. static int gfld_kick_thr;
  48. static int gfld_kick_time;
  49. static int gfld_join_thr;
  50. static int gfld_join_time;
  51. static int gfld_ctcp_thr;
  52. static int gfld_ctcp_time;
  53. static int gfld_nick_thr;
  54. static int gfld_nick_time;
  55. #ifdef S_AUTOLOCK
  56. int killed_bots = 0;
  57. #endif /* S_AUTOLOCK */
  58. #include "channels.h"
  59. #include "cmdschan.c"
  60. #include "tclchan.c"
  61. #include "userchan.c"
  62. /* This will close channels if the HUB:leaf count is skewed from config setting */
  63. void check_should_lock()
  64. {
  65. #ifdef S_AUTOLOCK
  66. #ifdef HUB
  67. char *p = CFG_LOCKTHRESHOLD.gdata;
  68. tand_t *bot = NULL;
  69. int H, L, hc, lc;
  70. struct chanset_t *chan = NULL;
  71. if (!p)
  72. return;
  73. H = atoi(p);
  74. p = strchr(p, ':');
  75. if (!p)
  76. return;
  77. p++;
  78. L = atoi(p);
  79. if ((H <= 0) || (L <= 0))
  80. return;
  81. hc = 1;
  82. lc = 0;
  83. for (bot = tandbot; bot; bot = bot->next) {
  84. struct userrec *u = get_user_by_handle(userlist, bot->bot);
  85. if (u) {
  86. if (bot_hublevel(u) < 999)
  87. hc++;
  88. else
  89. lc++;
  90. }
  91. }
  92. if ((hc >= H) && (lc <= L)) {
  93. for (chan = chanset; chan; chan = chan->next) {
  94. if (!channel_closed(chan)) {
  95. do_chanset(NULL, chan, "+closed chanmode +stni", DO_LOCAL | DO_NET);
  96. #ifdef G_BACKUP
  97. chan->channel.backup_time = now + 30;
  98. #endif /* G_BACKUP */
  99. }
  100. }
  101. }
  102. #endif /* HUB */
  103. #endif /* S_AUTOLOCK */
  104. }
  105. static void got_cset(char *botnick, char *code, char *par)
  106. {
  107. int all = 0;
  108. char *chname = NULL;
  109. struct chanset_t *chan = NULL;
  110. if (!par || !par[0])
  111. return;
  112. else {
  113. if (par[0] == '*' && par[1] == ' ') {
  114. all = 1;
  115. newsplit(&par);
  116. } else {
  117. if (!strchr(CHANMETA, par[0])) {
  118. putlog(LOG_ERROR, "*", "Got bad cset: bot: %s code: %s par: %s", botnick, code, par);
  119. return;
  120. }
  121. chname = newsplit(&par);
  122. if (!(chan = findchan_by_dname(chname)))
  123. return;
  124. }
  125. }
  126. if (all)
  127. chan = chanset;
  128. while (chan) {
  129. chname = chan->dname;
  130. do_chanset(NULL, chan, par, DO_LOCAL);
  131. #ifdef LEAF
  132. if (chan->status & CHAN_BITCH)
  133. recheck_channel(chan, 0);
  134. #endif /* LEAF */
  135. if (!all)
  136. chan = NULL;
  137. else
  138. chan = chan->next;
  139. }
  140. }
  141. /* returns 1 if botn is in bots */
  142. static int
  143. parsebots(char *bots, char *botn) {
  144. if (!strcmp(bots, "*")) {
  145. return 1;
  146. } else {
  147. char *list = NULL, *bot = NULL;
  148. list = strdup(bots);
  149. bot = strtok(list, ",");
  150. while(bot && *bot) {
  151. if (!egg_strcasecmp(bot, botn))
  152. return 1;
  153. bot = strtok((char*) NULL, ",");
  154. }
  155. free(list);
  156. }
  157. return 0;
  158. }
  159. static void got_cpart(char *botnick, char *code, char *par)
  160. {
  161. char *chname = NULL, *bots = NULL;
  162. struct chanset_t *chan = NULL;
  163. int match = 0;
  164. if (!par[0])
  165. return;
  166. chname = newsplit(&par);
  167. if (!(chan = findchan_by_dname(chname)))
  168. return;
  169. bots = newsplit(&par);
  170. match = parsebots(bots, conf.bot->nick);
  171. if (match)
  172. do_chanset(NULL, chan, "+inactive", DO_LOCAL);
  173. else
  174. remove_channel(chan);
  175. #ifdef HUB
  176. write_userfile(-1);
  177. #endif /* HUB */
  178. }
  179. static void got_cjoin(char *botnick, char *code, char *par)
  180. {
  181. char *chname = NULL, *options = NULL;
  182. #ifdef LEAF
  183. char *bots = NULL;
  184. int match = 0, inactive = 0;
  185. #endif /* LEAF */
  186. struct chanset_t *chan = NULL;
  187. if (!par[0])
  188. return;
  189. chname = newsplit(&par);
  190. chan = findchan_by_dname(chname);
  191. /* ALL hubs should add the channel, leaf should check the list for a match */
  192. #ifdef LEAF
  193. bots = newsplit(&par);
  194. if (strstr(par, "+inactive"))
  195. inactive = 1;
  196. match = parsebots(bots, conf.bot->nick);
  197. if (chan && !match)
  198. return;
  199. if (!match) {
  200. size_t size = strlen(par) + 12 + 1;
  201. options = calloc(1, size);
  202. egg_snprintf(options, size, "%s +inactive", par);
  203. } else if (match && chan && !shouldjoin(chan)) {
  204. if (!inactive)
  205. do_chanset(NULL, chan, "-inactive", DO_LOCAL);
  206. return;
  207. } else
  208. #endif /* LEAF */
  209. options = par;
  210. if (chan)
  211. return;
  212. sdprintf("OPTIONS: %s", options);
  213. if (channel_add(NULL, chname, options) == ERROR) /* drummer */
  214. putlog(LOG_BOTS, "@", "Invalid channel or channel options from %s for %s", botnick, chname);
  215. #ifdef HUB
  216. else
  217. write_userfile(-1);
  218. #endif /* HUB */
  219. #ifdef LEAF
  220. if (!match)
  221. free(options);
  222. #endif /* LEAF */
  223. }
  224. #ifdef LEAF
  225. static void got_cycle(char *botnick, char *code, char *par)
  226. {
  227. char *chname = NULL;
  228. struct chanset_t *chan = NULL;
  229. int delay = 10;
  230. if (!par[0])
  231. return;
  232. chname = newsplit(&par);
  233. if (!(chan = findchan_by_dname(chname)))
  234. return;
  235. if (par[0])
  236. delay = atoi(newsplit(&par));
  237. do_chanset(NULL, chan, "+inactive", DO_LOCAL);
  238. dprintf(DP_SERVER, "PART %s\n", chan->name);
  239. chan->channel.jointime = ((now + delay) - server_lag); /* rejoin in 10 seconds */
  240. }
  241. static void got_down(char *botnick, char *code, char *par)
  242. {
  243. char *chname = NULL;
  244. struct chanset_t *chan = NULL;
  245. if (!par[0])
  246. return;
  247. chname = newsplit(&par);
  248. if (!(chan = findchan_by_dname(chname)))
  249. return;
  250. chan->channel.no_op = (now + 10);
  251. add_mode(chan, '-', 'o', botname);
  252. }
  253. #endif /* LEAF */
  254. static void got_role(char *botnick, char *code, char *par)
  255. {
  256. char *tmp = NULL;
  257. tmp = newsplit(&par);
  258. role = atoi(tmp);
  259. if (par[0]) {
  260. tmp = newsplit(&par);
  261. timesync = atoi(tmp) - now;
  262. }
  263. putlog(LOG_DEBUG, "@", "Got role index %d", role);
  264. }
  265. void got_kl(char *botnick, char *code, char *par)
  266. {
  267. #ifdef S_AUTOLOCK
  268. killed_bots++;
  269. if (kill_threshold && (killed_bots = kill_threshold)) {
  270. struct chanset_t *ch = NULL;
  271. for (ch = chanset; ch; ch = ch->next)
  272. do_chanset(NULL, ch, "+closed +backup +bitch", DO_LOCAL | DO_NET);
  273. /* FIXME: we should randomize nick here ... */
  274. }
  275. #endif /* S_AUTOLOCK */
  276. }
  277. #ifdef HUB
  278. void rebalance_roles()
  279. {
  280. struct bot_addr *ba = NULL;
  281. int r[5] = { 0, 0, 0, 0, 0 };
  282. unsigned int hNdx, lNdx, i;
  283. char tmp[10] = "";
  284. for (i = 0; i < (unsigned) dcc_total; i++) {
  285. if (dcc[i].user && (dcc[i].user->flags & USER_BOT)) {
  286. ba = get_user(&USERENTRY_BOTADDR, dcc[i].user);
  287. if (ba && (ba->roleid > 0) && (ba->roleid < 5))
  288. r[(ba->roleid - 1)]++;
  289. }
  290. }
  291. /*
  292. Find high & low
  293. while (high-low) > 2
  294. move from highNdx to lowNdx
  295. */
  296. hNdx = 0;
  297. lNdx = 0;
  298. for (i = 1; i <= 4; i++) {
  299. if (r[i] < r[lNdx])
  300. lNdx = i;
  301. if (r[i] > r[hNdx])
  302. hNdx = i;
  303. }
  304. while (r[hNdx] - r[lNdx] >= 2) {
  305. for (i = 0; i < (unsigned) dcc_total; i++) {
  306. if (dcc[i].user && (dcc[i].user->flags & USER_BOT)) {
  307. ba = get_user(&USERENTRY_BOTADDR, dcc[i].user);
  308. if (ba && (ba->roleid == (hNdx + 1))) {
  309. ba->roleid = lNdx + 1;
  310. sprintf(tmp, "rl %d %li", lNdx + 1, timesync + now);
  311. putbot(dcc[i].nick, tmp);
  312. }
  313. }
  314. }
  315. r[hNdx]--;
  316. r[lNdx]++;
  317. hNdx = 0;
  318. lNdx = 0;
  319. for (i = 1; i <= 4; i++) {
  320. if (r[i] < r[lNdx])
  321. lNdx = i;
  322. if (r[i] > r[hNdx])
  323. hNdx = i;
  324. }
  325. }
  326. }
  327. #endif /* HUB */
  328. static void channels_10secondly() {
  329. struct chanset_t *chan = NULL;
  330. for (chan = chanset; chan; chan = chan->next) {
  331. /* slowpart */
  332. if (channel_active(chan) && (chan->channel.parttime) && (chan->channel.parttime < now)) {
  333. chan->channel.parttime = 0;
  334. #ifdef LEAF
  335. dprintf(DP_MODE, "PART %s\n", chan->name);
  336. #endif /* LEAF */
  337. if (chan) /* this should NOT be necesary, but some unforseen bug requires it.. */
  338. remove_channel(chan);
  339. break; /* if we keep looping, we'll segfault. */
  340. /* slowjoin */
  341. } else if ((chan->channel.jointime) && (chan->channel.jointime < now)) {
  342. chan->status &= ~CHAN_INACTIVE;
  343. chan->channel.jointime = 0;
  344. #ifdef LEAF
  345. if (shouldjoin(chan) && !channel_active(chan))
  346. dprintf(DP_MODE, "JOIN %s %s\n", chan->name, chan->key_prot);
  347. } else if (channel_closed(chan)) {
  348. enforce_closed(chan);
  349. #endif /* LEAF */
  350. }
  351. }
  352. }
  353. static void got_sj(int idx, char *code, char *par)
  354. {
  355. char *chname = NULL;
  356. time_t delay;
  357. struct chanset_t *chan = NULL;
  358. chname = newsplit(&par);
  359. delay = ((atoi(par) + now) - server_lag);
  360. chan = findchan_by_dname(chname);
  361. if (chan)
  362. chan->channel.jointime = delay;
  363. }
  364. static void got_sp(int idx, char *code, char *par)
  365. {
  366. char *chname = NULL;
  367. time_t delay;
  368. struct chanset_t *chan = NULL;
  369. chname = newsplit(&par);
  370. delay = ((atoi(par) + now) - server_lag);
  371. chan = findchan_by_dname(chname);
  372. if (chan)
  373. chan->channel.parttime = delay;
  374. }
  375. /* got_jn
  376. * We get this when a bot is opped in a +take chan
  377. * we are to set -inactive, jointime = 0, and join.
  378. */
  379. static void got_jn(int idx, char *code, char *par)
  380. {
  381. struct chanset_t *chan = NULL;
  382. char *chname = NULL;
  383. chname = newsplit(&par);
  384. if (!chname || !chname[0]) return;
  385. if (!(chan = findchan_by_dname(chname))) return;
  386. if (chan->channel.jointime && channel_inactive(chan)) {
  387. chan->status &= ~CHAN_INACTIVE;
  388. chan->channel.jointime = 0;
  389. #ifdef LEAF
  390. if (shouldjoin(chan) && !channel_active(chan))
  391. dprintf(DP_MODE, "JOIN %s %s\n", chan->name, chan->key_prot);
  392. #endif /* LEAF */
  393. }
  394. }
  395. static void set_mode_protect(struct chanset_t *chan, char *set)
  396. {
  397. int i, pos = 1;
  398. char *s = NULL, *s1 = NULL;
  399. /* Clear old modes */
  400. chan->mode_mns_prot = chan->mode_pls_prot = 0;
  401. chan->limit_prot = 0;
  402. chan->key_prot[0] = 0;
  403. for (s = newsplit(&set); *s; s++) {
  404. i = 0;
  405. switch (*s) {
  406. case '+':
  407. pos = 1;
  408. break;
  409. case '-':
  410. pos = 0;
  411. break;
  412. case 'i':
  413. i = CHANINV;
  414. break;
  415. case 'p':
  416. i = CHANPRIV;
  417. break;
  418. case 's':
  419. i = CHANSEC;
  420. break;
  421. case 'm':
  422. i = CHANMODER;
  423. break;
  424. case 'c':
  425. i = CHANNOCLR;
  426. break;
  427. case 'C':
  428. i = CHANNOCTCP;
  429. break;
  430. case 'R':
  431. i = CHANREGON;
  432. break;
  433. case 'M':
  434. i = CHANMODR;
  435. break;
  436. case 'r':
  437. i = CHANLONLY;
  438. break;
  439. case 't':
  440. i = CHANTOPIC;
  441. break;
  442. case 'n':
  443. i = CHANNOMSG;
  444. break;
  445. case 'a':
  446. i = CHANANON;
  447. break;
  448. case 'q':
  449. i = CHANQUIET;
  450. break;
  451. case 'l':
  452. i = CHANLIMIT;
  453. chan->limit_prot = 0;
  454. if (pos) {
  455. s1 = newsplit(&set);
  456. if (s1[0] && !chan->limitraise)
  457. chan->limit_prot = atoi(s1);
  458. }
  459. break;
  460. case 'k':
  461. i = CHANKEY;
  462. chan->key_prot[0] = 0;
  463. if (pos) {
  464. s1 = newsplit(&set);
  465. if (s1[0])
  466. strcpy(chan->key_prot, s1);
  467. }
  468. break;
  469. }
  470. if (i) {
  471. if (pos) {
  472. chan->mode_pls_prot |= i;
  473. chan->mode_mns_prot &= ~i;
  474. } else {
  475. chan->mode_pls_prot &= ~i;
  476. chan->mode_mns_prot |= i;
  477. }
  478. }
  479. }
  480. /* Prevents a +s-p +p-s flood (fixed by drummer) */
  481. if (chan->mode_pls_prot & CHANSEC)
  482. chan->mode_pls_prot &= ~CHANPRIV;
  483. }
  484. static void get_mode_protect(struct chanset_t *chan, char *s)
  485. {
  486. char *p = s, s1[121] = "";
  487. int ok = 0, i, tst;
  488. for (i = 0; i < 2; i++) {
  489. ok = 0;
  490. if (i == 0) {
  491. tst = chan->mode_pls_prot;
  492. if ((tst) || (chan->limit_prot != 0) || (chan->key_prot[0]))
  493. *p++ = '+';
  494. if (chan->limit_prot != 0) {
  495. *p++ = 'l';
  496. sprintf(&s1[strlen(s1)], "%d ", chan->limit_prot);
  497. }
  498. if (chan->key_prot[0]) {
  499. *p++ = 'k';
  500. sprintf(&s1[strlen(s1)], "%s ", chan->key_prot);
  501. }
  502. } else {
  503. tst = chan->mode_mns_prot;
  504. if (tst)
  505. *p++ = '-';
  506. if (tst & CHANKEY)
  507. *p++ = 'k';
  508. if (tst & CHANLIMIT)
  509. *p++ = 'l';
  510. }
  511. if (tst & CHANINV)
  512. *p++ = 'i';
  513. if (tst & CHANPRIV)
  514. *p++ = 'p';
  515. if (tst & CHANSEC)
  516. *p++ = 's';
  517. if (tst & CHANMODER)
  518. *p++ = 'm';
  519. if (tst & CHANNOCLR)
  520. *p++ = 'c';
  521. if (tst & CHANNOCTCP)
  522. *p++ = 'C';
  523. if (tst & CHANREGON)
  524. *p++ = 'R';
  525. if (tst & CHANMODR)
  526. *p++ = 'M';
  527. if (tst & CHANLONLY)
  528. *p++ = 'r';
  529. if (tst & CHANTOPIC)
  530. *p++ = 't';
  531. if (tst & CHANNOMSG)
  532. *p++ = 'n';
  533. if (tst & CHANANON)
  534. *p++ = 'a';
  535. if (tst & CHANQUIET)
  536. *p++ = 'q';
  537. }
  538. *p = 0;
  539. if (s1[0]) {
  540. s1[strlen(s1) - 1] = 0;
  541. strcat(s, " ");
  542. strcat(s, s1);
  543. }
  544. }
  545. /* Returns true if this is one of the channel masks
  546. */
  547. int ismodeline(masklist *m, const char *username)
  548. {
  549. for (; m && m->mask[0]; m = m->next)
  550. if (!rfc_casecmp(m->mask, username))
  551. return 1;
  552. return 0;
  553. }
  554. /* Returns true if user matches one of the masklist -- drummer
  555. */
  556. int ismasked(masklist *m, const char *username)
  557. {
  558. for (; m && m->mask[0]; m = m->next)
  559. if (wild_match(m->mask, (char *) username))
  560. return 1;
  561. return 0;
  562. }
  563. /* Unlink chanset element from chanset list.
  564. */
  565. __inline__ static int chanset_unlink(struct chanset_t *chan)
  566. {
  567. struct chanset_t *c = NULL, *c_old = NULL;
  568. for (c = chanset; c; c_old = c, c = c->next) {
  569. if (c == chan) {
  570. if (c_old)
  571. c_old->next = c->next;
  572. else
  573. chanset = c->next;
  574. return 1;
  575. }
  576. }
  577. return 0;
  578. }
  579. /* Completely removes a channel.
  580. *
  581. * This includes the removal of all channel-bans, -exempts and -invites, as
  582. * well as all user flags related to the channel.
  583. */
  584. void remove_channel(struct chanset_t *chan)
  585. {
  586. int i;
  587. /* Remove the channel from the list, so that noone can pull it
  588. away from under our feet during the check_part() call. */
  589. chanset_unlink(chan);
  590. #ifdef LEAF
  591. do_channel_part(chan);
  592. #endif /* LEAF */
  593. clear_channel(chan, 0);
  594. noshare = 1;
  595. /* Remove channel-bans */
  596. while (chan->bans)
  597. u_delmask('b', chan, chan->bans->mask, 1);
  598. /* Remove channel-exempts */
  599. while (chan->exempts)
  600. u_delmask('e', chan, chan->exempts->mask, 1);
  601. /* Remove channel-invites */
  602. while (chan->invites)
  603. u_delmask('I', chan, chan->invites->mask, 1);
  604. /* Remove channel specific user flags */
  605. user_del_chan(chan->dname);
  606. noshare = 0;
  607. free(chan->channel.key);
  608. for (i = 0; i < 6 && chan->cmode[i].op; i++)
  609. free(chan->cmode[i].op);
  610. if (chan->key)
  611. free(chan->key);
  612. if (chan->rmkey)
  613. free(chan->rmkey);
  614. free(chan);
  615. }
  616. /* Bind this to chon and *if* the users console channel == ***
  617. * then set it to a specific channel
  618. */
  619. static int channels_chon(char *handle, int idx)
  620. {
  621. struct flag_record fr = {FR_CHAN | FR_ANYWH | FR_GLOBAL, 0, 0};
  622. int find, found = 0;
  623. struct chanset_t *chan = chanset;
  624. if (dcc[idx].type == &DCC_CHAT) {
  625. if (!findchan_by_dname(dcc[idx].u.chat->con_chan) &&
  626. ((dcc[idx].u.chat->con_chan[0] != '*') ||
  627. (dcc[idx].u.chat->con_chan[1] != 0))) {
  628. get_user_flagrec(dcc[idx].user, &fr, NULL);
  629. if (glob_op(fr))
  630. found = 1;
  631. if (chan_owner(fr))
  632. find = USER_OWNER;
  633. else if (chan_master(fr))
  634. find = USER_MASTER;
  635. else
  636. find = USER_OP;
  637. fr.match = FR_CHAN;
  638. while (chan && !found) {
  639. get_user_flagrec(dcc[idx].user, &fr, chan->dname);
  640. if (fr.chan & find)
  641. found = 1;
  642. else
  643. chan = chan->next;
  644. }
  645. if (!chan)
  646. chan = chanset;
  647. if (chan)
  648. strcpy(dcc[idx].u.chat->con_chan, chan->dname);
  649. else
  650. strcpy(dcc[idx].u.chat->con_chan, "*");
  651. }
  652. }
  653. return 0;
  654. }
  655. static cmd_t my_chon[] =
  656. {
  657. {"*", "", (Function) channels_chon, "channels:chon"},
  658. {NULL, NULL, NULL, NULL}
  659. };
  660. void channels_report(int idx, int details)
  661. {
  662. struct chanset_t *chan = NULL;
  663. int i;
  664. char s[1024] = "", s2[100] = "";
  665. struct flag_record fr = {FR_CHAN | FR_GLOBAL, 0, 0};
  666. for (chan = chanset; chan; chan = chan->next) {
  667. if (idx != DP_STDOUT)
  668. get_user_flagrec(dcc[idx].user, &fr, chan->dname);
  669. if (!private(fr, chan, PRIV_OP) && ((idx == DP_STDOUT) || glob_master(fr) || chan_master(fr))) {
  670. s[0] = 0;
  671. if (channel_bitch(chan))
  672. strcat(s, "bitch, ");
  673. if (s[0])
  674. s[strlen(s) - 2] = 0;
  675. if (!s[0])
  676. strcpy(s, MISC_LURKING);
  677. get_mode_protect(chan, s2);
  678. if (channel_closed(chan)) {
  679. strcat(s2, "i");
  680. if (chan->closed_private)
  681. strcat(s2, "p");
  682. }
  683. if (shouldjoin(chan)) {
  684. if (channel_active(chan)) {
  685. /* If it's a !chan, we want to display it's unique name too <cybah> */
  686. if (chan->dname[0]=='!') {
  687. dprintf(idx, " %-10s: %2d member%s enforcing \"%s\" (%s), "
  688. "unique name %s\n", chan->dname, chan->channel.members,
  689. (chan->channel.members==1) ? "," : "s,", s2, s, chan->name);
  690. } else {
  691. dprintf(idx, " %-10s: %2d member%s enforcing \"%s\" (%s)\n",
  692. chan->dname, chan->channel.members,
  693. chan->channel.members == 1 ? "," : "s,", s2, s);
  694. }
  695. } else {
  696. #ifdef LEAF
  697. dprintf(idx, " %-10s: (%s), enforcing \"%s\" (%s)\n", chan->dname,
  698. channel_pending(chan) ? "pending" : "not on channel", s2, s);
  699. #else /* !LEAF */
  700. dprintf(idx, " %-10s: (%s), enforcing \"%s\" (%s)\n", chan->dname,
  701. "limbo", s2, s);
  702. #endif /* LEAF */
  703. }
  704. } else {
  705. dprintf(idx, " %-10s: channel is set +inactive\n",
  706. chan->dname);
  707. }
  708. if (details) {
  709. s[0] = 0;
  710. i = 0;
  711. i += my_strcpy(s + i, "dynamic ");
  712. if (channel_enforcebans(chan))
  713. i += my_strcpy(s + i, "enforcebans ");
  714. if (channel_dynamicbans(chan))
  715. i += my_strcpy(s + i, "dynamicbans ");
  716. if (!channel_nouserbans(chan))
  717. i += my_strcpy(s + i, "userbans ");
  718. if (channel_bitch(chan))
  719. i += my_strcpy(s + i, "bitch ");
  720. if (channel_protectops(chan))
  721. i += my_strcpy(s + i, "protectops ");
  722. if (channel_revenge(chan))
  723. i += my_strcpy(s + i, "revenge ");
  724. if (channel_revenge(chan))
  725. i += my_strcpy(s + i, "revengebot ");
  726. if (channel_secret(chan))
  727. i += my_strcpy(s + i, "secret ");
  728. if (channel_cycle(chan))
  729. i += my_strcpy(s + i, "cycle ");
  730. if (channel_dynamicexempts(chan))
  731. i += my_strcpy(s + i, "dynamicexempts ");
  732. if (!channel_nouserexempts(chan))
  733. i += my_strcpy(s + i, "userexempts ");
  734. if (channel_dynamicinvites(chan))
  735. i += my_strcpy(s + i, "dynamicinvites ");
  736. if (!channel_nouserinvites(chan))
  737. i += my_strcpy(s + i, "userinvites ");
  738. if (!shouldjoin(chan))
  739. i += my_strcpy(s + i, "inactive ");
  740. if (channel_nodesynch(chan))
  741. i += my_strcpy(s + i, "nodesynch ");
  742. if (channel_closed(chan))
  743. i += my_strcpy(s + i, "closed ");
  744. if (channel_take(chan))
  745. i += my_strcpy(s + i, "take ");
  746. if (channel_nomop(chan))
  747. i += my_strcpy(s + i, "nmop ");
  748. if (channel_manop(chan))
  749. i += my_strcpy(s + i, "manop ");
  750. if (channel_voice(chan))
  751. i += my_strcpy(s + i, "voice ");
  752. if (channel_autoop(chan))
  753. i += my_strcpy(s + i, "autoop ");
  754. /* Chanflag template
  755. * if (channel_temp(chan))
  756. * i += my_strcpy(s + i, "temp ");
  757. */
  758. if (channel_fastop(chan))
  759. i += my_strcpy(s + i, "fastop ");
  760. if (channel_private(chan))
  761. i += my_strcpy(s + i, "private ");
  762. dprintf(idx, " Options: %s\n", s);
  763. if (chan->idle_kick)
  764. dprintf(idx, " Kicking idle users after %d min\n",
  765. chan->idle_kick);
  766. if (chan->limitraise)
  767. dprintf(idx, " Raising limit +%d every 2 minutes\n", chan->limitraise);
  768. if (chan->stopnethack_mode)
  769. dprintf(idx, " stopnethack-mode %d\n",
  770. chan->stopnethack_mode);
  771. if (chan->revenge_mode)
  772. dprintf(idx, " revenge-mode %d\n",
  773. chan->revenge_mode);
  774. dprintf(idx, " Bans last %d mins.\n", chan->ban_time);
  775. dprintf(idx, " Exemptions last %d mins.\n", chan->exempt_time);
  776. dprintf(idx, " Invitations last %d mins.\n", chan->invite_time);
  777. }
  778. }
  779. }
  780. }
  781. cmd_t channels_bot[] = {
  782. {"cjoin", "", (Function) got_cjoin, NULL},
  783. {"cpart", "", (Function) got_cpart, NULL},
  784. {"cset", "", (Function) got_cset, NULL},
  785. #ifdef LEAF
  786. {"cycle", "", (Function) got_cycle, NULL},
  787. {"down", "", (Function) got_down, NULL},
  788. #endif /* LEAF */
  789. {"rl", "", (Function) got_role, NULL},
  790. {"kl", "", (Function) got_kl, NULL},
  791. {"sj", "", (Function) got_sj, NULL},
  792. {"sp", "", (Function) got_sp, NULL},
  793. {"jn", "", (Function) got_jn, NULL},
  794. /*
  795. #ifdef HUB
  796. {"o1", "", (Function) got_o1, NULL},
  797. {"kl", "", (Function) got_kl, NULL},
  798. #endif
  799. {"ltp", "", (Function) got_locktopic, NULL},
  800. */
  801. {NULL, NULL, NULL, NULL}
  802. };
  803. #ifdef LEAF
  804. static void check_limitraise() {
  805. int i = 0;
  806. static int checklimit = 1;
  807. struct chanset_t *chan = NULL;
  808. for (chan = chanset; chan; chan = chan->next, i++) {
  809. if (i % 2 == checklimit && chan->limitraise && dolimit(chan))
  810. raise_limit(chan);
  811. }
  812. if (checklimit)
  813. checklimit = 0;
  814. else
  815. checklimit = 1;
  816. }
  817. #endif /* LEAF */
  818. void channels_init()
  819. {
  820. gfld_chan_thr = 0;
  821. gfld_chan_time = 0;
  822. gfld_deop_thr = 8;
  823. gfld_deop_time = 10;
  824. gfld_kick_thr = 0;
  825. gfld_kick_time = 0;
  826. gfld_join_thr = 0;
  827. gfld_join_time = 0;
  828. gfld_ctcp_thr = 0;
  829. gfld_ctcp_time = 0;
  830. global_idle_kick = 0;
  831. lastdeletedmask = 0;
  832. use_info = 1;
  833. strcpy(glob_chanmode, "nt");
  834. global_stopnethack_mode = 0;
  835. global_revenge_mode = 3;
  836. global_ban_time = 0;
  837. global_exempt_time = 0;
  838. global_invite_time = 0;
  839. strcpy(glob_chanset,
  840. "+enforcebans "
  841. "+dynamicbans "
  842. "+userbans "
  843. "-bitch "
  844. "-protectops "
  845. "-revenge "
  846. "+cycle "
  847. "-inactive "
  848. "+userexempts "
  849. "-dynamicexempts "
  850. "+userinvites "
  851. "-dynamicinvites "
  852. "-revengebot "
  853. "-nodesynch "
  854. "-closed "
  855. "-take "
  856. "+manop "
  857. "-voice "
  858. "-private "
  859. "-fastop ");
  860. #ifdef LEAF
  861. timer_create_secs(60, "check_limitraise", (Function) check_limitraise);
  862. #endif /* LEAF */
  863. #ifdef HUB
  864. timer_create_secs(30, "rebalance_roles", (Function) rebalance_roles);
  865. #endif /* HUB */
  866. timer_create_secs(60, "check_expired_bans", (Function) check_expired_bans);
  867. timer_create_secs(60, "check_expired_exempts", (Function) check_expired_exempts);
  868. timer_create_secs(60, "check_expired_invites", (Function) check_expired_invites);
  869. timer_create_secs(10, "channels_10secondly", (Function) channels_10secondly);
  870. add_builtins("dcc", C_dcc_irc);
  871. add_builtins("bot", channels_bot);
  872. add_builtins("chon", my_chon);
  873. }