mnet.tcl 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. ## Why this?
  2. # There was some nifty bot on QuakeNet which forwarded messages to other bots.
  3. # Its main purpose was to simplify match-organisation for 3d-shooter games.
  4. #
  5. # When a clan wanted to play a game, they simply had to do something like:
  6. # .qw let's play 4on4, come to 194.162.154.124:27500
  7. # so every bot on the botnet received that message and forwarded it to other
  8. # clanchannels.
  9. #
  10. # The technology was first made by someone, but was not released by him. As far
  11. # as I can remember, it was a Q3-Urban Terror player.
  12. # The QuakeWorld-scene was interested in his script, but since the Q3-UT guy didn't
  13. # want to opensource his script a QW-player made a re-engineering. But still,
  14. # he didn't release the source. The QW-scene still uses the re-engineered script.
  15. #
  16. # When I asked the QW-scene guys for it, they didn't want THEIR re-engineered
  17. # project open sourced or even given to me. So.....
  18. #
  19. # ... now, I made a re-engineering from scratch too AND released the source.
  20. # Free for all.
  21. #
  22. # Man, you all suck.
  23. #
  24. #
  25. # This script is not yet as complete as their "so super secret technology" is, but
  26. # I wrote the core of it in about two nightly hours. More to come.
  27. #
  28. # 23.05.2004 Haudrauf of Quadaver
  29. # contact me if you want to contribute code snippets: #quadaver on QuakeNet
  30. ## CONFIG AND SOMEHOW README-SECTION FOLLOWS
  31. # You just have to connect your bots in a common eggdrop-botnet. Of course, every bot
  32. # has to have the same script installed.
  33. # The script uses "putallbots" to send messages to all linked bots on the botnet. Except
  34. # stated otherwhise here... but default is "0" to send to all bots.
  35. # A bot which doesn't have the script installed simply ignores the message though.. so,
  36. # who cares?
  37. set mnet(defined_bots) "0"
  38. # So here, you can chose the bots, where to send the messages to, by name.
  39. # You need to have mnet(defined_bots) "1", if you want to use the botlist below.
  40. # If you accidently added a bot here, which doesn't exist, it's no problem at all.. a small
  41. # errormessage will appear on the partyline.
  42. # WARNING: Recommendation is to have mnet(defined_bots) "0"!
  43. set mnet(bots) {"QUADAVER" "AQ2_01" "MyOwnBot"}
  44. # Here you set the channels of THIS bot, where you want received messages
  45. # to post to:
  46. set mnet(ownchannels) {"#pickup.aq2" "#quad.aq2"}
  47. #set mnet(ownchannels) {"#narf" "#action.dac" "#duel.aq2" "#we>you" "#[pulse]" "#action-nt.ger" "#mobsters" "#refugees" "#ace.aq2" "#only_human" "#akuh" "#q-aq2" "#mif" "#clan-duel" "#s4p" "#clan.fwd" "#sumpen" "#stener" "#dipunishment"}
  48. #set mnet(ownchannels) {"#extacy" "#cold!" "#aq2.cup" "#dpl.aq2" "#aq2world" "#clan-raw" "#attention!" "#rip" "#clan-Xk" "#clan-end"}
  49. # Set a Loglevel: 1 or 2
  50. # 1 means: who, where, from
  51. # 2 means: who, where, from, what(text)
  52. set mnet(loglevel) "2"
  53. ###### Now, here are some important settings. Every bot in your network should have the same!
  54. ###### otherwise it sucks..
  55. # banlist of ppl who are not allowed to use this bot.
  56. # this suxx... need a centralized version of this
  57. set mnetbans(1) {"*!*@*.quakenet.org" ""}
  58. # When a user wants to send a message, does he have to use .aq2 or .qw or something else? :)
  59. # Easily specify your public command:
  60. set mnet(public_cmd) ".aq2"
  61. # Set 1 or 0 here, whether you want to answer a posting request by the number of reached users.
  62. # nice idea to set to 1, thx. :)
  63. set mnet(answer) "1"
  64. # Here, you set the message layout. The prefix is how your messages begin with
  65. set mnet(prefix) "-AQ2-"
  66. # Display a nice helpmessage if someone only typed the public_cmd without arguments.
  67. set mnet(usage) "dot$mnet(prefix): Usage: '$mnet(public_cmd) need 4on4 at 20:00.' Rules: ONLY $mnet(prefix)related, only english and no replies over the bot! Use query or join their channel!"
  68. # Set the color.. 02 blue, 03 green, 05, red .. and so on, easy irc-colors.
  69. set mnet(color) "03"
  70. #############################################################################
  71. # Now, hands away pls :) except you know what you are doing.
  72. set mnet(version) "mnet 0.666haui"
  73. set mnet(reached) "0"
  74. set mnet(reached_channels) "0"
  75. bind pub - $mnet(public_cmd) mnet:messaging_public
  76. bind bot - mnet_send mnet:receive_message
  77. bind bot - mnet_answer mnet:receive_answer
  78. proc mnet:get_data {n} {
  79. if {[string range $n 0 0] == "\{"} {
  80. set n "\\$n"
  81. }
  82. return $n
  83. }
  84. proc mnet:put_local_message {chan rec_nickname rec_channel rec_text} {
  85. global mnet
  86. puthelp "PRIVMSG $chan :$mnet(prefix) \003$mnet(color)$rec_nickname - $rec_channel : $rec_text"
  87. if {$mnet(loglevel) == "1"} {
  88. putlog "mnet: + local message from $rec_nickname @ $rec_channel to $chan"
  89. } elseif {$mnet(loglevel) == "2"} {
  90. putlog "mnet: + local message from $rec_nickname @ $rec_channel to $chan : $rec_text"
  91. }
  92. }
  93. proc mnet:put_nick {nick msg} {
  94. putserv "NOTICE $nick :$msg"
  95. }
  96. proc mnet:put_bot {botnick data} {
  97. set testlink [islinked $botnick]
  98. if {$testlink == "1"} {
  99. putbot $botnick $data
  100. } else {
  101. putlog "mnet: + Message couldn't be delivered. Bot $botnick is not linked"
  102. }
  103. }
  104. proc mnet:chanstat_users {chan users} {
  105. set ch_users [chanlist $chan]
  106. set ch_users_count [llength $ch_users]
  107. set users [expr $users + $ch_users_count]
  108. return $users
  109. }
  110. ## procs which are executed remotely follow:
  111. proc mnet:receive_message {rec_botnick cmd rec_data} {
  112. global mnet
  113. set rec_nickname [mnet:get_data [lindex $rec_data 0]]
  114. set rec_channel [lindex $rec_data 1]
  115. set rec_text [lrange $rec_data 2 end]
  116. set rec_text [mnet:clean_txt $rec_text]
  117. if {$mnet(loglevel) == "1"} {
  118. putlog "mnet: + Relaying Message from: $rec_nickname @ $rec_botnick @ $rec_channel"
  119. } elseif {$mnet(loglevel) == "2"} {
  120. putlog "mnet: + Relaying Message from: $rec_nickname @ $rec_botnick @ $rec_channel: $rec_text"
  121. }
  122. set users 0
  123. set count_channels 0
  124. foreach chan $mnet(ownchannels) {
  125. if {[mnet:botonchannel $chan] == "1"} {
  126. incr count_channels
  127. set users [mnet:chanstat_users $chan $users]
  128. putlog "mnet: * Remote counting $chan users: $users"
  129. mnet:put_local_message $chan $rec_nickname $rec_channel $rec_text
  130. } else {
  131. putlog "mnet: + Can't relay a message to '$chan' since I am not there."
  132. }
  133. }
  134. # ANSWER! SEND!
  135. if {$mnet(answer) == "1"} {
  136. mnet:put_bot $rec_botnick "mnet_answer $users $count_channels"
  137. }
  138. return 0
  139. }
  140. proc mnet:receive_answer {rec_botnick cmd rec_data} {
  141. global mnet
  142. set rec_usercount [lindex $rec_data 0]
  143. set rec_chancount [lindex $rec_data 1]
  144. # set rec_text [lrange $rec_data 2 end]
  145. # get this bots results to our global variable:
  146. set mnet(reached) [expr $mnet(reached) + $rec_usercount]
  147. set mnet(reached_channels) [expr $mnet(reached_channels) + $rec_chancount]
  148. putlog "mnet: * $rec_botnick told me he sent its message to $rec_usercount people in $rec_chancount channels!"
  149. putlog "mnet: * Users reached since .aq2: $mnet(reached) in channels: $mnet(reached_channels)"
  150. }
  151. proc mnet:clean_txt {text} {
  152. regsub "{" $text "" text
  153. regsub "}" $text "" text
  154. regsub -all "\003\[0-9\]\[0-9\]" $text "" text
  155. regsub -all "\003\[0-9\]" $text "" text
  156. regsub -all "\003" $text "" text
  157. regsub -all "\002" $text "" text
  158. # putlog "test: $text"
  159. set text [string trim $text]
  160. return $text
  161. }
  162. proc mnet:botonchannel {chan} {
  163. # safe "bot-knows-the-channel-and-is-in-there"-function
  164. if {[validchan $chan] == "1" && [botonchan $chan] == "1"} {
  165. return 1
  166. } else {
  167. return 0
  168. }
  169. }
  170. proc mnet:messaging_public {nick mask hand chan text} {
  171. # proc triggered by .aq2 and calling the following (internal) one
  172. global mnet botnick
  173. putlog "mnet: = triggered by $nick ($mask) in $chan"
  174. # the command must be from a channel of "ownchannels"
  175. set found 0
  176. foreach _trigger_chan $mnet(ownchannels) {
  177. # putlog "mnet: = trying $_trigger_chan"
  178. if {$_trigger_chan == $chan} {
  179. # putlog "mnet: = found channel: $_trigger_chan"
  180. set found 1
  181. } else {
  182. # putlog "mnet: = not in list: $chan"
  183. }
  184. }
  185. if {$found == 0} {
  186. putlog "mnet: = not allowed in: $chan"
  187. return invalid_channel
  188. }
  189. set snd_nick [mnet:get_data $nick]
  190. if {![isop $nick $chan] && $nick != $botnick} {
  191. putlog "mnet: = allowed in $chan, but $nick is no op"
  192. mnet:put_nick $nick "Sorry $nick, you need to be op."
  193. return not_an_op
  194. }
  195. # check here if we have some text or not.. :)
  196. # cleaning string...
  197. set text [mnet:clean_txt $text]
  198. if {$text == "" || $text == "{}"} {
  199. # output some help:
  200. putlog "mnet: = gave him some help"
  201. puthelp "PRIVMSG $chan :$mnet(usage)"
  202. } else {
  203. set mnet(reached) "0"
  204. set mnet(reached_channels) "0"
  205. # send them first, we await a reply!
  206. # single sends TO ALL REMOTE BOTS with their remote CHANNELS...
  207. # let's see which mode for sending is used...
  208. if {$mnet(defined_bots) == "1"} {
  209. foreach _botnick $mnet(bots) {
  210. if {$_botnick == $botnick} {
  211. } else { # if not myself!
  212. # safe put_bot function..
  213. mnet:put_bot $_botnick "mnet_send $snd_nick $chan $text"
  214. if {$mnet(loglevel) == "1"} {
  215. putlog "mnet: + Sending a message to $_botnick"
  216. } elseif {$mnet(loglevel) == "2"} {
  217. putlog "mnet: + Sending a message to $_botnick : $text"
  218. }
  219. }
  220. }
  221. } else { # if not "defined_bots"
  222. putallbots "mnet_send $snd_nick $chan $text"
  223. if {$mnet(loglevel) == "1"} {
  224. putlog "mnet: + Sending a message to all linked bots!"
  225. } elseif {$mnet(loglevel) == "2"} {
  226. putlog "mnet: + Sending a message to all linked bots: $text"
  227. }
  228. }
  229. # SEND TO ALL OWN CHANNELS...
  230. # send to all own channels, except to the channel the message originating from:
  231. foreach _ownchan $mnet(ownchannels) {
  232. if {$_ownchan == $chan} {
  233. } else { # if not own channel!
  234. if {[mnet:botonchannel $_ownchan] == "1"} {
  235. putlog "mnet: = i am on $_ownchan"
  236. # userstats local
  237. set mnet(reached) [mnet:chanstat_users $_ownchan $mnet(reached)]
  238. putlog "mnet: * Localcounting up $_ownchan users: $mnet(reached)"
  239. # channel count local
  240. incr mnet(reached_channels)
  241. mnet:put_local_message $_ownchan $snd_nick $chan $text
  242. } else {
  243. putlog "mnet: + Can't send a local message to '$_ownchan' since I am not there."
  244. }
  245. }
  246. }
  247. # wait here some more! (10 seconds with utimer)
  248. utimer 5 "mnet:reply_timeout {$chan}"
  249. # notice: better would be to go into the "reply" when all known bots already answered..
  250. # then, if a bot is missing, but it was a known bot, just use a timeout with about 5-10 seconds..
  251. # if the bot still didn't answer, then just go into "reply".
  252. }
  253. }
  254. proc mnet:reply_timeout {chan} {
  255. global mnet
  256. # inzwischen dürfte auch die antwort gekommen sein.. also jetzt mnet(reached) auswerten nach timeout..
  257. putlog "mnet: * After all: Count_Users: $mnet(reached) Count_Channels: $mnet(reached_channels)"
  258. # Give me some reply.
  259. puthelp "PRIVMSG $chan :Message sent to $mnet(reached) users in $mnet(reached_channels) channels."
  260. }
  261. proc mnet:check_ban {nick mask} {
  262. global mnet(banlist)
  263. foreach bmask $banmask {
  264. if {[string match [string tolower $bmask] [string tolower $bmask_check]]} {
  265. newchanban $chan $bmask_host BanMask "$bmask_reason" $bmask_time
  266. sendnote BanMask $bmask_notify "÷ banned $bmask_check on $chan, [ctime [unixtime]] ÷"
  267. if {[botisop $chan]} {
  268. putserv "MODE $chan -o+b $nick $bmask_host"
  269. putserv "KICK $chan $nick :$bmask_reason"
  270. }
  271. break
  272. }
  273. }
  274. }
  275. putlog "mnet: = Messaging Network ($mnet(version)) loaded"