Guest User

Untitled

a guest
Apr 11th, 2018
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 19.39 KB | None | 0 0
  1. --bot.rb--
  2.  
  3. require 'socket' # Required to connect to server
  4. require 'timeout' # Required for status queue checking
  5. require 'mysql'
  6. require File.dirname(__FILE__) + '/Plugin'
  7.  
  8. # Default config Variables
  9.  
  10. $db = Mysql.new("localhost", "root")
  11. $db.select_db("bot")
  12. config = $db.query( "select * from config" )
  13. config =config.fetch_hash
  14. $channels = $db.query( "select channel from channels where serverid ='#{config['id']}'" )
  15.  
  16. class Bot
  17.  
  18. # Instance vars that may be read/written externally.
  19. attr_writer :sock
  20. attr_reader :sock
  21.  
  22. # Constructor
  23. def initialize(config)
  24. # General config variables
  25. @server = config["server"]
  26. @port = config["port"]
  27. $nick = config["nick"]
  28. @altnick = config["altnick"]
  29. @realname = config["realname"]
  30. $admin = config["admin"]
  31. $owner = $admin;
  32. $admin_pass = config["admin_pass"]
  33. # True servername (declare to supress initialization warnings).
  34. @servername = nil
  35.  
  36. # Info hash (for tracking user info).
  37.  
  38. @info = Hash.new()
  39.  
  40. # Buffer hash (declare 'all' key to supress initialization warnings).
  41. $buffer = { 'all' => nil }
  42. end
  43.  
  44. # Initialize the socket.
  45. def initSocket
  46. puts "Connecting to #{@server} on port #{@port}"
  47. @sock = TCPSocket.new(@server, @port)
  48. end
  49.  
  50. # Send a PRIVMSG.
  51. def msg(channel, msg)
  52. if msg =~ /(.+)?(\[.+\])(.+)?/i
  53. msg = "#{$1}#{$2}#{$3}"
  54. end
  55. self.cmd("PRIVMSG #{channel} :#{msg}");
  56. end
  57.  
  58. def msgbox(type, msg)
  59. max = 0
  60. text = ""
  61. msg.each_line do |line|
  62. line = line.strip
  63. if line.length > max
  64. max = line.length + 2
  65. end
  66.  
  67. end
  68. msg.each_line do |line|
  69. line = line.strip
  70. len = max - 2 - line.length
  71. text = "#{text}| #{line}"
  72. count = 0
  73. while count != len
  74. text = "#{text} "
  75. count = count + 1
  76. end
  77. text = "#{text} |\n"
  78. end
  79. count = 0
  80. line=""
  81. while count != max
  82. line = "#{line}-"
  83. count = count + 1
  84. end
  85. count = 0
  86. remove = line.length - type.length - 2
  87. limit = remove / 2
  88. while count != limit
  89. firstline = "#{firstline}-"
  90. count = count + 1
  91. end
  92. puts "\n+#{firstline}[#{type.upcase}]#{firstline}+\n#{text}+#{line}+"
  93. if type.upcase == "FATAL ERROR"
  94. exit
  95. end
  96. end
  97. # Send a raw command.
  98. def cmd(command)
  99. # Optional, document (log) sent data.
  100. self.doc(command);
  101.  
  102. # Send raw command.
  103. @sock.puts(command);
  104. end
  105.  
  106. # Log received data.
  107. def log(buf)
  108. # Print to screen.
  109. puts '>> ' + buf
  110.  
  111. # Hack to determine own hostname.
  112. if buf =~ /:#{$nick}!(.+)@(\S+) (.+)/
  113. @hostname = $2
  114. end
  115.  
  116. # Optional log to file or db.
  117. end
  118.  
  119. # Log sent data (document).
  120. def doc(buf)
  121. # Print to screen.
  122. puts '<< ' + buf
  123.  
  124. # Optional log to file or db.
  125. end
  126.  
  127. def isOperator(nick, channel)
  128. if @info[channel.upcase.strip][nick.upcase.strip]['mode'].include? "\~" or
  129. @info[channel.upcase.strip][nick.upcase.strip]['mode'].include? "\@" or
  130. @info[channel.upcase.strip][nick.upcase.strip]['mode'].include? "\&"
  131. return true
  132. end
  133.  
  134. return false
  135. end
  136.  
  137. # Flush the buffer, without destroying array structure
  138. def flush
  139. # For each key in the hash, set to nil.
  140. $buffer.each_key {|key| $buffer[key] = nil}
  141. end
  142.  
  143. # Parse the buffer, and fetch tokens.
  144. def parse_buffer(buf)
  145. $buffer['all'] = buf;
  146.  
  147. # If it is a standard line (MODE, PRIVMSG, JOIN, etc..)
  148. if buf.chomp =~ /:(.+)!(.+)@(\S+) (.+)/
  149. $buffer['username'] = $1
  150. $buffer['ident'] = $2
  151. $buffer['hostname'] = $3
  152. buffet = $4 # buffet === buffer snippet
  153.  
  154. case buffet
  155. when /JOIN :(.+)/i
  156. $buffer['command'] = "JOIN"
  157. $buffer['channel'] = $1
  158. # Get info for @info hash
  159. # A bit hackish.. wish not to request on every JOIN -- could be a drain / lag
  160. self.cmd("WHO #{$buffer['username']}")
  161. # Auto voice users.
  162. unless $buffer['username'].include? $nick
  163. self.cmd("MODE #{$buffer['channel']} +v #{$buffer['username']}")
  164. end
  165. when /^PART (\S+) :?(.*)/i
  166. $buffer['command'] = "PART"
  167. $buffer['channel'] = $1
  168. $buffer['argument'] = $2
  169. # Remove user from status hash.
  170. @info[$1.upcase][$buffer['username'].upcase] = nil
  171. when /QUIT :?(.*)/i
  172. $buffer['command'] = "QUIT"
  173. $buffer['argument'] = $1
  174. # Remove user from status hash.
  175. @info.each_key {|x| @info[x.upcase][$buffer['username'].upcase] = nil}
  176. when /PRIVMSG (.+) :(.+)/i
  177. $buffer['command'] = "PRIVMSG"
  178. $buffer['argument'] = $2
  179. $buffer['channel'] = $1
  180. # When we get a true private message, the channel will be our nick,
  181. # so to reply, let's force channel to be the user who sent the message.
  182. $buffer['channel'] = $buffer['username'] if $buffer['channel'] =~ /^#{$nick}$/i
  183. when /NICK :(\S+)/i
  184. $buffer['command'] = "NICK"
  185. # Move users statuses to new username, remove old instances
  186. @info.each_key do |_ch|
  187. if @info[_ch.upcase][$buffer['username'].upcase] != nil
  188. @info[_ch.upcase][$1.upcase.strip] = Hash.new()
  189. @info[_ch.upcase][$1.upcase.strip] = @info[_ch.upcase][$buffer['username'].upcase]
  190. @info[_ch.upcase][$buffer['username'].upcase] = nil
  191. puts 'changed'
  192. end
  193. end
  194. $buffer['username'] = $1
  195. when /MODE (\S+) (.+)/i
  196. $buffer['command'] = "MODE"
  197. $buffer['channel'] = $1
  198. $buffer['argument'] = $2
  199. when /KICK (\S+) (\S+)(\s:){0,1}(.*)/i
  200. $buffer['command'] = "KICK"
  201. $buffer['channel'] = $1
  202. $buffer['victim'] = $2
  203. $buffer['argument'] = $4
  204. # Remove user from status hash.
  205. @info[$1.upcase][$2.upcase] = nil
  206. when /NOTICE (.+) :(.+)/i
  207. $buffer['command'] = "NOTICE"
  208. $buffer['channel'] = $1
  209. $buffer['argument'] = $2
  210.  
  211. # Default
  212. else
  213. $buffer['command'] = "UNDEFINED"
  214. end
  215. end
  216. end
  217.  
  218. # Process commands triggered by server messages.
  219. def process_directives
  220. # Connection established. Send information.
  221. if $buffer['all'] =~ /NOTICE AUTH :\*\*\* (checking ident|Found your hostname \(cached\))/i
  222. self.cmd("NICK #{$nick}")
  223. self.cmd("USER #{$nick} 0 * :#{@realname}")
  224. self.cmd("MODE #{$nick} +iw")
  225. end
  226.  
  227. # Duplicate nick, use alternative.
  228. if $buffer['all'] =~ /433/
  229. self.cmd("NICK #{@altnick}")
  230. self.cmd("USER #{@altnick} 0 * :#{@realname}")
  231. end
  232.  
  233. # Handshake.
  234. if $buffer['all'] =~ /001/
  235. @servername = $`.to_s.strip
  236. end
  237.  
  238. # This is the correct way to join a channel.
  239. # Wait first for the MOTD to finish, then proceed.
  240. if $buffer['all'] =~ /#{@servername} (376|422) #{$nick}/
  241. chans = $channels.num_rows
  242. i=0
  243. while i != chans
  244. self.cmd("JOIN #{$channels.fetch_row}")
  245. i = i + 1
  246. end
  247. end
  248.  
  249. # Reply to PING's with the same argument.
  250. if $buffer['all'] =~ /PING :(.+)/
  251. self.cmd("PONG :#{$1}")
  252. end
  253.  
  254. if $buffer['all'] =~ /ERROR :Closing Link|Server Terminating/i
  255. exit 0
  256. end
  257.  
  258. # NAMES
  259. # if $buffer['all'] =~ /353/
  260. #
  261. # end
  262.  
  263. #
  264. if $buffer['all'] =~ /366 #{$nick} (\S+)/i
  265. self.cmd( "WHO #{$1}")
  266. end
  267.  
  268. #
  269. if $buffer['all'] =~ /352 #{$nick} (\S+) (\S+) (\S+) (\S+) (\S+) (\S+) :(\S+) (.*)/i
  270. @info[$1.upcase] = Hash.new() if @info[$1.upcase] == nil
  271. @info[$1.upcase][$5.upcase] = Hash.new()
  272. @info[$1.upcase][$5.upcase]['ident'] = $2
  273. @info[$1.upcase][$5.upcase]['host'] = $3
  274. @info[$1.upcase][$5.upcase]['leaf'] = $4
  275. @info[$1.upcase][$5.upcase]['mode'] = $6 #
  276. @info[$1.upcase][$5.upcase]['hops'] = $7
  277. @info[$1.upcase][$5.upcase]['extra'] = $8
  278. end
  279.  
  280. end
  281.  
  282. # Process commands triggerd by text, mode, kick, (etc).
  283. def process_commands
  284. case $buffer['command']
  285. when "PRIVMSG"
  286.  
  287. if $buffer['argument'] =~ /^.auth (.*) (.*)/i
  288. user = $1
  289. pass = $2
  290. if user == $admin and pass == $admin_pass
  291. self.cmd("MODE #{@channel} +o #{$buffer['username']}")
  292. $owner = $buffer['username']
  293. self.msg($buffer['channel'], "Hello #{$buffer['username']}, You are now this bot's owner")
  294. puts $owner + " is now owner of this bot"
  295. end
  296. end
  297.  
  298. if $buffer['argument'] =~ /^.die (.*)/i
  299. pass = $1
  300. if pass == $admin_pass
  301. self.cmd("QUIT :Shutdown Requested by #{$buffer['username']}")
  302. end
  303. end
  304.  
  305. # Auto greet reply
  306. if $buffer['argument'] =~ /^(hi|yo|hey|howdy|hola|sup|salut|greetings|hello) #{$nick}/i
  307. self.msg($buffer['channel'], "yo #{$buffer['username']}.")
  308. end
  309.  
  310. # whoami
  311. if $buffer['argument'] =~ /^.whoami/i
  312. self.msg($buffer['channel'], "username : #{$buffer['username']}")
  313. self.msg($buffer['channel'], "ident : #{$buffer['ident']}")
  314. self.msg($buffer['channel'], "hostname : #{$buffer['hostname']}")
  315. end
  316.  
  317. # reverse
  318. if $buffer['argument'] =~ /^.reverse (.+)/i
  319. self.msg($buffer['channel'], $1.chomp.reverse)
  320. end
  321.  
  322.  
  323. # count
  324. if $buffer['argument'] =~ /^.count (.+)/i
  325. self.msg($buffer['channel'], "Length is #{$1.chomp.length}")
  326. end
  327.  
  328. # action template
  329. if $buffer['argument'] =~ /ACTION (.+)/i
  330. # self.msg($buffer['channel'], $buffer['argument'])
  331. end
  332.  
  333. # raw execution
  334. if $buffer['argument'] =~ /^.exec (.+)/i
  335. if $buffer['username'].include? $owner
  336. self.cmd($1)
  337. else
  338. self.msg($buffer['channel'], "No No, me no exec your commands, go do '" + $1 + "' yourself k? cool thnx buhbye")
  339. self.msg($admin, $buffer['channel'] + " just tried to execute " + $1)
  340. end
  341. end
  342.  
  343. # fetch user status. "what is bob in #chan"
  344. if $buffer['argument'] =~ /^what is (.+) (in|on) (.+)/i
  345. _nick = $1.upcase.strip
  346. _chan = $3.upcase.strip
  347. if @info[_chan] != nil
  348. if @info[_chan][_nick] != nil
  349. if @info[_chan][_nick]['mode'].include? "\~"
  350. self.msg($buffer['channel'], "Owner")
  351. elsif @info[_chan][_nick]['mode'].include? "\&"
  352. self.msg($buffer['channel'], "Protected")
  353. elsif @info[_chan][_nick]['mode'].include? "\@"
  354. self.msg($buffer['channel'], "Operator")
  355. elsif @info[_chan][_nick]['mode'].include? "\%"
  356. self.msg($buffer['channel'], "Half-Op")
  357. elsif @info[_chan][_nick]['mode'].include? "\+"
  358. self.msg($buffer['channel'], "Voiced")
  359. else
  360. self.msg($buffer['channel'], "Normal User")
  361. end
  362. else
  363. self.msg($buffer['channel'], "I don't see them.")
  364. end
  365. end
  366. end
  367.  
  368. if $buffer['argument'] =~ /^.fetch (\S+) (.+)/i
  369. if @info[$1.upcase] != nil
  370. if @info[$1.upcase][$2.upcase.strip] != nil
  371. self.msg($buffer['channel'], "Ident: #{@info[$1.upcase][$2.upcase.strip]['ident']}")
  372. self.msg($buffer['channel'], "Host : #{@info[$1.upcase][$2.upcase.strip]['host']}")
  373. self.msg($buffer['channel'], "Leaf : #{@info[$1.upcase][$2.upcase.strip]['leaf']}")
  374. self.msg($buffer['channel'], "Mode : #{@info[$1.upcase][$2.upcase.strip]['mode']}")
  375. self.msg($buffer['channel'], "Hops : #{@info[$1.upcase][$2.upcase.strip]['hops']}")
  376. self.msg($buffer['channel'], "Extra: #{@info[$1.upcase][$2.upcase.strip]['extra']}")
  377. end
  378. end
  379. end
  380. if $buffer['argument'] =~ /^.help/i
  381. self.msg($buffer['channel'], "[HELP] Available Commands are as follows:")
  382. self.msg($buffer['channel'], "[HELP] .help")
  383. self.msg($buffer['channel'], "[HELP] .whoami")
  384. self.msg($buffer['channel'], "[HELP] .auth USER PASSWORD")
  385. self.msg($buffer['channel'], "[HELP] .count STRING")
  386. self.msg($buffer['channel'], "[HELP] .reverse STRING")
  387. self.msg($buffer['channel'], "[HELP] .fetch CHANNEL USER")
  388. self.msg($buffer['channel'], "[HELP] what is USER in|on CHANNEL")
  389. self.msg($buffer['channel'], "[HELP] .plugin_list (INACTIVE | ACTIVE | ALL)")
  390. self.msg($buffer['channel'], "[HELP] .plugin_activate PLUGINAME")
  391. self.msg($buffer['channel'], "[HELP] .plugin_deactivate PLUGINAME")
  392. self.msg($buffer['channel'], "[HELP] .plugin_about PLUGINAME")
  393. $commands.each do |com|
  394. self.msg($buffer['channel'], "[HELP] #{com[1]}")
  395. end
  396. end
  397. if $buffer['argument'] =~ /^.plugin_(.*) (.+)/i
  398. mode = $1
  399. args = $2
  400. if mode == "list"
  401. if args.upcase == "INACTIVE"
  402. Plugin.list_deact
  403. elsif args.upcase == "ACTIVE"
  404. Plugin.list_act
  405. elsif args.upcase == "ALL"
  406. Plugin.list_act
  407. Plugin.list_deact
  408. else
  409. self.msg($buffer['channel'], "[ERROR] Syntax of this command is \".plugin_list active/inactive/all\"")
  410. end
  411. end
  412. if mode == "activate"
  413. if $buffer['username'].include? $owner
  414. Plugin.act(args)
  415. end
  416. end
  417. if mode == "deactivate"
  418. if $buffer['username'].include? $owner
  419. Plugin.deact(args)
  420. end
  421. end
  422. if mode == "about" || mode == "describe"
  423. Plugin.about_plugin(args)
  424. end
  425. end
  426.  
  427. when "KICK"
  428. # If it is us, let's rejoin the channel.
  429. if $buffer['victim'] =~ /#{$nick}/i
  430. self.cmd("JOIN #{$buffer['channel']}")
  431. end
  432.  
  433. when "MODE"
  434. # If mode is a ban..
  435. # TODO: fix for multiple bans " +bbb *!*@*.net *!*@*.org *!*@*.com "
  436. if $buffer['argument'] =~ /\+b (.+)!(.+)@(.+)/i
  437. _n = $1 and _i = $2 and _h = $3
  438. _victim = "#{$1}!#{$2}@#{$3}"
  439.  
  440. # Create regular expressions from the ban mask
  441. _n.gsub!(/\*/, '(.*)')
  442. _i.gsub!(/^~/, '')
  443. _i.gsub!(/\*/, '(.*)')
  444. _h.gsub!(/\*/, '(.*)')
  445.  
  446. # If it is us.. let's kick/ban them, and unban ourselves.
  447. if $nick =~ /#{_n}/i and $nick =~ /#{_i}/i and @hostname =~ /#{_h}/i
  448.  
  449. self.cmd("KICK #{$buffer['channel']} #{$buffer['username']} :<3 #{$nick}")
  450.  
  451. # Create a ban mask from the user doing the ban " *!*ident*@*.host "
  452. _ident = $1 if $buffer['ident'] =~ /~?(.+)/i
  453. _host = $1 if $buffer['hostname'] =~ /[a-zA-Z\-]+\.(.+)/i
  454.  
  455. self.cmd("MODE #{$buffer['channel']} +b *!*#{_ident}@*.#{_host}")
  456. self.cmd("MODE #{$buffer['channel']} -b #{_victim}")
  457. end
  458. end
  459.  
  460. # If a + usermode change..
  461. if $buffer['all'] =~ /MODE (.+) (\+|\-)(\w)+ (.+)/i
  462. self.cmd("WHO #{$1}")
  463. end
  464.  
  465.  
  466. # Default
  467. else
  468. # some nop statement?
  469. x = nil
  470. end
  471.  
  472. # Clear buffer to avoid parsing multiple times.
  473. self.flush
  474. end
  475.  
  476. end
  477.  
  478. # Create the core object.
  479. @core = Bot.new(config)
  480. config = config.sort
  481. txt = ""
  482. for conf in config
  483. if conf[0] == "admin_pass"
  484.  
  485. else
  486. txt = "#{txt}#{conf[0]} => #{conf[1]}\n"
  487. end
  488. end
  489. $core.msgbox("config", txt)
  490. Plugin.LoadAll
  491. puts ""
  492. # Initialize the socket.
  493. begin
  494. $core.initSocket
  495. rescue
  496. $core.msgbox("fatal error", "Cannot connect to server (No Route to host)")
  497. end
  498. while true
  499.  
  500. begin
  501. Timeout::timeout(7) do |blah|
  502. # Read in text, line by line.
  503. while $buf = $core.sock.gets do
  504. # Log to screen and or file / db.
  505. $core.log($buf)
  506. # Parse buffer, fetch tokens.
  507. $core.parse_buffer($buf)
  508. Plugin.process($buf)
  509. # Process directives and commands.
  510. $core.process_directives
  511. $core.process_commands
  512. Plugin.run_freq
  513. end
  514.  
  515. end
  516.  
  517. rescue Timeout::Error
  518. Plugin.run_freq
  519. #exit
  520. end
  521.  
  522. end
  523.  
  524.  
  525.  
  526.  
  527. --Plugin.rb--
  528. class Plugin
  529. @loaded_plugins = {}
  530. @enabled_plugins = {}
  531. $commands = Hash.new()
  532. class << self
  533. attr_reader :loaded_plugins
  534. attr_reader :enabled_plugins
  535. private :new
  536. end
  537.  
  538. def self.define(name, &block)
  539. p = new
  540. p.instance_eval(&block)
  541. self.loaded_plugins[name] = p
  542. end
  543.  
  544. def self.mod(name, enabled)
  545. self.enabled_plugins[name] = enabled
  546. end
  547.  
  548.  
  549.  
  550. def self.LoadAll
  551. i=0
  552. a=0
  553. Dir[File.dirname(__FILE__) + "/plugins/*.rb"].each do |x|
  554. mods = $db.query( "select * from plugins" )
  555. mods.each do |y|
  556. if x.upcase.include? y[0]
  557. name = y[0]
  558. begin
  559. load x
  560. plugin = File.open(x).read
  561. plugin.each_line do |line|
  562. if line =~ /\/\^(\\\+|\\\.)(.+)\/i( \#)?(.+)?/i
  563. arg = $4
  564. $commands[a] = "#{$1}#{$2.gsub(/\?|\(|\.|\\S|\+|\\|\)|\*/i, '')} #{arg}".gsub(/\\/i, '')
  565. a = a + 1
  566. end
  567. end
  568. if y[1].to_i == 1
  569. self.mod(y[0],1)
  570. puts "Loading #{name} as enabled\n"
  571. else
  572. self.mod(y[0],0)
  573. puts "Loading #{name} as disabled\n"
  574. end
  575.  
  576. rescue
  577. puts "! #{name} contains errors and was not loaded !\n"
  578. end
  579.  
  580. end
  581. end
  582. end
  583. end
  584.  
  585. def self.act(mod)
  586. mod = mod.upcase
  587. self.enabled_plugins.each do |plugin|
  588. if plugin[0].include? mod
  589. if plugin[1] == 1
  590. $core.msg($buffer['channel'], "[ACTIVATE PLUGIN] #{mod.capitalize} already enabled")
  591. else
  592. $core.msg($buffer['channel'], "[ACTIVATE PLUGIN] #{mod.capitalize} is now enabled")
  593. self.mod(mod,1)
  594. modded = $db.query( "UPDATE plugins SET enabled = '1' WHERE mod_name = '#{mod}'" )
  595. end
  596. end
  597. end
  598. end
  599.  
  600. def self.list_act
  601. $core.msg($buffer['channel'], "[ACTIVE PLUGINS]")
  602. self.enabled_plugins.each do |plugin|
  603. if plugin[1] == 1
  604. $core.msg($buffer['channel'], "#{plugin[0].capitalize}")
  605. end
  606. end
  607. end
  608.  
  609. def self.list_deact
  610. $core.msg($buffer['channel'], "[INACTIVE PLUGINS]")
  611. self.enabled_plugins.each do |plugin|
  612. if plugin[1] == 0
  613. $core.msg($buffer['channel'], "#{plugin[0].capitalize}")
  614. end
  615. end
  616. end
  617.  
  618. def self.deact(mod)
  619. mod = mod.upcase
  620. self.enabled_plugins.each do |plugin|
  621. if plugin[0].include? mod
  622. if plugin[1] == 1
  623. $core.msg($buffer['channel'], "[DEACTIVATE PLUGIN] #{mod.capitalize} is now disabled")
  624. self.mod(mod,0)
  625. modded = $db.query( "UPDATE plugins SET enabled = '0' WHERE mod_name = '#{mod}'" )
  626. else
  627. $core.msg($buffer['channel'], "[DEACTIVATE PLUGIN] #{mod.capitalize} already disabled")
  628. end
  629. end
  630. end
  631. end
  632.  
  633. def self.about_plugin(mod)
  634. mod = mod.upcase.gsub(/ /i, '_')
  635. puts mod
  636. self.loaded_plugins.each do |plugin|
  637. if plugin[0] == mod
  638. if self.enabled_plugins[plugin[0]].to_i === 1
  639. plugin[1].about
  640. end
  641. end
  642. end
  643. end
  644.  
  645. def self.process(buf)
  646. self.loaded_plugins.each do |plugin|
  647. if self.enabled_plugins[plugin[0]].to_i === 1
  648. # If it is a standard line (MODE, PRIVMSG, JOIN, etc..)
  649. if buf.chomp =~ /:(.+)!(.+)@(\S+) (.+)/
  650. plugin[1].procedure()
  651. end
  652. end
  653. end
  654. end
  655.  
  656. def self.run_freq()
  657. self.loaded_plugins.each do |plugin|
  658. if self.enabled_plugins[plugin[0]].to_i === 1
  659. plugin[1].freq()
  660. end
  661. end
  662. end
  663. end
Add Comment
Please, Sign In to add comment