rbot 0.9.9 → 0.9.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. data/AUTHORS +8 -0
  2. data/ChangeLog +51 -0
  3. data/INSTALL +4 -0
  4. data/README +1 -0
  5. data/REQUIREMENTS +11 -0
  6. data/TODO +2 -0
  7. data/bin/rbot +21 -2
  8. data/data/rbot/languages/german.lang +4 -1
  9. data/data/rbot/languages/russian.lang +75 -0
  10. data/data/rbot/plugins/autoop.rb +42 -51
  11. data/data/rbot/plugins/bans.rb +205 -0
  12. data/data/rbot/plugins/bash.rb +56 -0
  13. data/data/rbot/plugins/chucknorris.rb +74 -0
  14. data/data/rbot/plugins/chucknorris.yml.gz +0 -0
  15. data/data/rbot/plugins/deepthoughts.rb +95 -0
  16. data/data/rbot/plugins/demauro.rb +95 -0
  17. data/data/rbot/plugins/digg.rb +51 -0
  18. data/data/rbot/plugins/figlet.rb +24 -0
  19. data/data/rbot/plugins/forecast.rb +133 -0
  20. data/data/rbot/plugins/freshmeat.rb +13 -7
  21. data/data/rbot/plugins/google.rb +2 -0
  22. data/data/rbot/plugins/grouphug.rb +36 -0
  23. data/data/rbot/plugins/imdb.rb +92 -0
  24. data/data/rbot/plugins/insult.rb +8 -1
  25. data/data/rbot/plugins/iplookup.rb +227 -0
  26. data/data/rbot/plugins/karma.rb +2 -2
  27. data/data/rbot/plugins/keywords.rb +470 -0
  28. data/data/rbot/plugins/lart.rb +132 -146
  29. data/data/rbot/plugins/lastfm.rb +25 -0
  30. data/data/rbot/plugins/markov.rb +204 -0
  31. data/data/rbot/plugins/math.rb +5 -1
  32. data/data/rbot/plugins/nickserv.rb +71 -11
  33. data/data/rbot/plugins/opme.rb +19 -19
  34. data/data/rbot/plugins/quakeauth.rb +2 -2
  35. data/data/rbot/plugins/quotes.rb +40 -25
  36. data/data/rbot/plugins/remind.rb +1 -1
  37. data/data/rbot/plugins/rot13.rb +2 -2
  38. data/data/rbot/plugins/roulette.rb +49 -15
  39. data/data/rbot/plugins/rss.rb +585 -0
  40. data/data/rbot/plugins/rubyurl.rb +39 -0
  41. data/data/rbot/plugins/seen.rb +2 -1
  42. data/data/rbot/plugins/slashdot.rb +5 -5
  43. data/data/rbot/plugins/spell.rb +5 -0
  44. data/data/rbot/plugins/theyfightcrime.rb +121 -0
  45. data/data/rbot/plugins/threat.rb +55 -0
  46. data/data/rbot/plugins/tinyurl.rb +39 -0
  47. data/data/rbot/plugins/topic.rb +204 -0
  48. data/data/rbot/plugins/urban.rb +71 -0
  49. data/data/rbot/plugins/url.rb +399 -4
  50. data/data/rbot/plugins/wow.rb +123 -0
  51. data/data/rbot/plugins/wserver.rb +1 -1
  52. data/data/rbot/templates/levels.rbot +2 -0
  53. data/lib/rbot/auth.rb +207 -96
  54. data/lib/rbot/channel.rb +5 -5
  55. data/lib/rbot/config.rb +125 -24
  56. data/lib/rbot/dbhash.rb +87 -21
  57. data/lib/rbot/httputil.rb +181 -13
  58. data/lib/rbot/ircbot.rb +525 -179
  59. data/lib/rbot/ircsocket.rb +330 -54
  60. data/lib/rbot/message.rb +66 -23
  61. data/lib/rbot/messagemapper.rb +25 -17
  62. data/lib/rbot/plugins.rb +244 -115
  63. data/lib/rbot/post-clean.rb +1 -0
  64. data/lib/rbot/{post-install.rb → post-config.rb} +1 -1
  65. data/lib/rbot/rbotconfig.rb +29 -14
  66. data/lib/rbot/registry.rb +111 -72
  67. data/lib/rbot/rfc2812.rb +208 -197
  68. data/lib/rbot/timer.rb +4 -0
  69. data/lib/rbot/utils.rb +2 -2
  70. metadata +127 -104
  71. data/data/rbot/plugins/rss.rb.disabled +0 -414
  72. data/lib/rbot/keywords.rb +0 -433
@@ -0,0 +1,39 @@
1
+ require "rubygems"
2
+ require "shorturl"
3
+
4
+ class RubyURL < Plugin
5
+
6
+ # return a help string when the bot is asked for help on this plugin
7
+ def help(plugin, topic="")
8
+ return "rubyurl <your long url>"
9
+ end
10
+
11
+ # reply to a private message that we've registered for
12
+ def privmsg(m)
13
+
14
+ # m.params contains the rest of the message, m.plugin contains the first
15
+ # word (useful because it's possible to register for multiple commands)
16
+ unless(m.params)
17
+ m.reply "incorrect usage. " + help(m.plugin)
18
+ end
19
+
20
+ # TODO: might want to add a check here to validate the url
21
+ # if they call 'rubyurl help' backwards, don't return a lame link
22
+
23
+ if (m.params == "help")
24
+ m.reply "Try again. Correct usage is: " + help(m.plugin)
25
+ return false
26
+ end
27
+
28
+ # call the ShortURL library with the value of the url
29
+ url = ShortURL.shorten(m.params)
30
+
31
+
32
+ m.reply "Your RubyURL: #{url}"
33
+
34
+ end
35
+ end
36
+
37
+ # create an instance of the RubyURL class and register it as a plugin
38
+ rubyurl = RubyURL.new
39
+ rubyurl.register("rubyurl")
@@ -21,6 +21,7 @@ class SeenPlugin < Plugin
21
21
  end
22
22
 
23
23
  def listen(m)
24
+ return if m.sourcenick.nil?
24
25
  # keep database up to date with who last said what
25
26
  if m.kind_of?(PrivMessage)
26
27
  return if m.private?
@@ -78,7 +79,7 @@ class SeenPlugin < Plugin
78
79
  when "JOIN"
79
80
  ret += "joining #{saw.where}"
80
81
  when "QUIT"
81
- ret += "quiting IRC (#{saw.message})"
82
+ ret += "quitting IRC (#{saw.message})"
82
83
  when "TOPIC"
83
84
  ret += "changing the topic of #{saw.where} to #{saw.message}"
84
85
  end
@@ -21,11 +21,11 @@ class SlashdotPlugin < Plugin
21
21
  m.reply "search for #{search} failed"
22
22
  return
23
23
  end
24
- puts xml.inspect
24
+ debug xml.inspect
25
25
  begin
26
26
  doc = Document.new xml
27
27
  rescue REXML::ParseException => e
28
- puts e
28
+ warning e.inspect
29
29
  m.reply "couldn't parse output XML: #{e.class}"
30
30
  return
31
31
  end
@@ -33,7 +33,7 @@ class SlashdotPlugin < Plugin
33
33
  m.reply "search for #{search} failed"
34
34
  return
35
35
  end
36
- puts doc.inspect
36
+ debug doc.inspect
37
37
  max = 8 if max > 8
38
38
  done = 0
39
39
  doc.elements.each("*/item") {|e|
@@ -50,9 +50,9 @@ class SlashdotPlugin < Plugin
50
50
  end
51
51
 
52
52
  def slashdot(m, params)
53
- puts params.inspect
53
+ debug params.inspect
54
54
  max = params[:limit].to_i
55
- puts "max is #{max}"
55
+ debug "max is #{max}"
56
56
  xml = @bot.httputil.get(URI.parse("http://slashdot.org/slashdot.xml"))
57
57
  unless xml
58
58
  m.reply "slashdot news parse failed"
@@ -14,18 +14,23 @@ class SpellPlugin < Plugin
14
14
  p.each_line {|l|
15
15
  if(l =~ /^\*/)
16
16
  m.reply "#{m.params} may be spelled correctly"
17
+ p.close
17
18
  return
18
19
  elsif(l =~ /^\s*&.*: (.*)$/)
19
20
  m.reply "#{m.params}: #$1"
21
+ p.close
20
22
  return
21
23
  elsif(l =~ /^\s*\+ (.*)$/)
22
24
  m.reply "#{m.params} is presumably derived from " + $1.downcase
25
+ p.close
23
26
  return
24
27
  elsif(l =~ /^\s*#/)
25
28
  m.reply "#{m.params}: no suggestions"
29
+ p.close
26
30
  return
27
31
  end
28
32
  }
33
+ p.close
29
34
  else
30
35
  m.reply "couldn't exec ispell :("
31
36
  return
@@ -0,0 +1,121 @@
1
+ HE = [
2
+
3
+ ['a superhumanly strong','an underprivileged','a globe-trotting','an impetuous','a shy','a suave','a notorious','a one-legged','an all-American','a short-sighted','an otherworldly','a hate-fuelled','a scrappy','an unconventional','a jaded','a leather-clad','a fiendish','a Nobel prize-winning','a suicidal','a maverick','a bookish','an old-fashioned','a witless','a lounge-singing','a war-weary','a scarfaced','a gun-slinging','an obese','a time-tossed','a benighted','an uncontrollable','an immortal','an oversexed','a world-famous','an ungodly','a fast talking','a deeply religious','a lonely','a sword-wielding','a genetically engineered'],
4
+
5
+ ['white trash','zombie','shark-wrestling','playboy','guitar-strumming','Jewish',
6
+ 'sweet-toothed','bohemian','crooked','chivalrous','moralistic','amnesiac','devious','drug-addicted',
7
+ 'voodoo','Catholic','overambitious','coffee-fuelled','pirate','misogynist','skateboarding',
8
+ 'arachnophobic','Amish','small-town','Republican','one-eyed','gay','guerilla','vegetarian',
9
+ 'dishevelled','alcoholic','flyboy','ninja','albino','hunchbacked','neurotic','umbrella-wielding',
10
+ 'native American','soccer-playing','day-dreaming'],
11
+
12
+ ['grifter','stage actor','paramedic','gentleman spy','jungle king','hairdresser',
13
+ 'photographer','ex-con','vagrant','filmmaker','werewolf','senator','romance novelist','shaman','cop',
14
+ 'rock star','farmboy','cat burglar','cowboy','cyborg','inventor','assassin','boxer','dog-catcher',
15
+ 'master criminal','gangster','firefighter','househusband','dwarf','librarian','paranormal investigator',
16
+ 'Green Beret','waffle chef','vampire hunter','messiah','astronaut','sorceror','card sharp','matador',
17
+ 'barbarian'],
18
+
19
+ ['with a robot buddy named Sparky.','whom everyone believes is mad.','gone bad.',
20
+ 'with a mysterious suitcase handcuffed to his arm.','living undercover at Ringling Bros. Circus.',
21
+ 'searching for his wife''s true killer.','who dotes on his loving old ma.','looking for ''the Big One.''',
22
+ 'who knows the secret of the alien invasion.','on the edge.','on a mission from God.','with a secret.',
23
+ 'in drag.','plagued by the memory of his family''s brutal murder.','looking for a cure to the poison coursing through his veins.',
24
+ 'moving from town to town, helping folk in trouble.',
25
+ 'who must take medication to keep him sane.','who hangs with the wrong crowd.',
26
+ 'possessed of the uncanny powers of an insect.','with a winning smile and a way with the ladies.',
27
+ 'fleeing from a secret government programme.','from the ''hood.','haunted by an iconic dead American confidante.',
28
+ 'with a passion for fast cars.','trapped in a world he never made.','in a wheelchair.',
29
+ 'on the hunt for the last specimen of a great and near-mythical creature.','on the run.',
30
+ 'for the 21st century.','who hides his scarred face behind a mask.','on the wrong side of the law.',
31
+ 'with no name.','from the Mississippi delta.','with acid for blood.','with nothing left to lose.',
32
+ 'haunted by memories of ''Nam.','on a search for his missing sister.','on his last day in the job.',
33
+ 'from a doomed world.','who believes he can never love again.']
34
+
35
+ ]
36
+
37
+ SHE = [
38
+
39
+ ['a radical','a green-fingered','a tortured','a time-travelling','a vivacious',
40
+ 'a scantily clad','a mistrustful','a violent','a transdimensional','a strong-willed','a ditzy','a man-hating',
41
+ 'a high-kicking','a blind','an elegant','a supernatural','a foxy','a bloodthirsty','a cynical','a beautiful',
42
+ 'a plucky','a sarcastic','a psychotic','a hard-bitten','a manipulative','an orphaned','a cosmopolitan',
43
+ 'a chain-smoking','a cold-hearted','a warm-hearted','a sharp-shooting','an enchanted','a wealthy','a pregnant',
44
+ 'a mentally unstable','a virginal','a brilliant','a disco-crazy','a provocative','an artistic'],
45
+
46
+ ['tempestuous', 'Buddhist', 'foul-mouthed', 'nymphomaniac', 'green-skinned', 'impetuous', 'African-American','punk','hypochondriac','junkie','blonde','goth','insomniac','gypsy','mutant','renegade', 'tomboy','French-Canadian','motormouth','belly-dancing','communist','hip-hop','thirtysomething',
47
+ 'cigar-chomping','extravagent','out-of-work','Bolivian','mute','cat-loving','snooty','wisecracking',
48
+ 'red-headed','winged','kleptomaniac','antique-collecting','psychic','gold-digging','bisexual','paranoid',
49
+ 'streetsmart'],
50
+
51
+ ['archaeologist','pearl diver','mechanic','detective','hooker','femme fatale',
52
+ 'former first lady','barmaid','fairy princess','magician''s assistant','schoolgirl','college professor',
53
+ 'angel','bounty hunter','opera singer','cab driver','soap star','doctor','politician','lawyer','nun',
54
+ 'snake charmer','journalist','bodyguard','vampire','stripper','Valkyrie','wrestler','mermaid','single mother',
55
+ 'safe cracker','traffic cop','research scientist','queen of the dead','Hell''s Angel','museum curator',
56
+ 'advertising executive','widow','mercenary','socialite'],
57
+
58
+ ['on her way to prison for a murder she didn''t commit.','trying to make a difference in a man''s world.',
59
+ 'with the soul of a mighty warrior.','looking for love in all the wrong places.','with an MBA from Harvard.',
60
+ 'who hides her beauty behind a pair of thick-framed spectacles.','with the power to see death.',
61
+ 'descended from a line of powerful witches.','from a family of eight older brothers.','with a flame-thrower.',
62
+ 'with her own daytime radio talk show.','living on borrowed time.','who can talk to animals.',
63
+ 'prone to fits of savage, blood-crazed rage.','who don''t take no shit from nobody.','with a knack for trouble.',
64
+ 'who believes she is the reincarnation of an ancient Egyptian queen.','fleeing from a Satanic cult.',
65
+ 'on the trail of a serial killer.','with a birthmark shaped like Liberty''s torch.',
66
+ 'in the witness protection scheme.','from out of town.','from aristocratic European stock.',
67
+ 'living homeless in New York''s sewers.','with only herself to blame.','from beyond the grave',
68
+ 'married to the Mob.','from the wrong side of the tracks.','from a secret island of warrior women.',
69
+ 'from Mars.','with someone else''s memories.','from a different time and place.','operating on the wrong side of the law.',
70
+ 'who inherited a spooky stately manor from her late maiden aunt.','who dreams of becoming Elvis.',
71
+ 'with a song in her heart and a spring in her step.','in the wrong place at the wrong time.',
72
+ 'with an incredible destiny.','with the power to bend men''s minds.','with an evil twin sister.']
73
+
74
+ ]
75
+
76
+ TITLE = [
77
+
78
+ ['FATAL', 'PRIMAL', 'BASIC', 'LETHAL',
79
+ 'FINAL', 'CLEAR', 'DIRTY', 'RED', 'FOREIGN', 'PRIMARY', 'EXECUTIVE',
80
+ 'BLOOD', 'HARD', 'STEEL', 'TERMINAL', 'HOT', 'COLD', 'TOTAL', 'PROGNOSIS:',
81
+ 'BURNING', 'FAST', 'PAINFUL', 'MISSION:', 'DEADLY', 'PARTIAL',
82
+ 'RAGING', 'CORDIAL'],
83
+
84
+ ['DECISION', 'INCISION', 'CONCLUSION',
85
+ 'CONCUSSION', 'HEAT', 'FIRE', 'RECOIL', 'INSTINCT', 'DESIRE', 'WEAPON',
86
+ 'BADGE', 'DEED', 'JUSTICE', 'HEAT', 'VENGEANCE', 'RECESSION', 'COMBUSTION',
87
+ 'JUDGEMENT', 'WARNING', 'AWAKENING', 'JURISDICTION', 'BASIS', 'FINDINGS',
88
+ 'INJECTION', 'REJECTION', 'REMISSION', 'DIGESTION', 'IDENTITY',
89
+ 'DISPERSION'],
90
+
91
+ ['II','III','IV','V','VI','VII','VIII','IX','X','XI','XII','XIII','XIV','XV','XVI','XVII','XVIII','XIX']
92
+
93
+ ]
94
+
95
+ class TheyFightCrime < Plugin
96
+ def help(plugin, topic="")
97
+ "movieplot => generate a random movie scenario. movietitle => generate a random movie title."
98
+ end
99
+
100
+ def get_random_things(thing_array)
101
+ thing_array.map { |things| things[rand(things.length)] }
102
+ end
103
+
104
+ def do_movieplot(m, params)
105
+ he_things = get_random_things(HE)
106
+ she_things = get_random_things(SHE)
107
+ m.reply "Summary: He's #{he_things.join " "} She's #{she_things.join " "} They fight crime."
108
+ end
109
+
110
+ def do_movietitle(m, params)
111
+ title_things = get_random_things(TITLE)
112
+ m.reply "Title: #{title_things.join " "}"
113
+ end
114
+ end
115
+
116
+ plugin = TheyFightCrime.new
117
+ plugin.map 'movieplot', :action => 'do_movieplot'
118
+ plugin.map 'movietitle', :action => 'do_movietitle'
119
+
120
+
121
+
@@ -0,0 +1,55 @@
1
+ # Security threat level plugin for rbot
2
+ # by Robin Kearney (robin@riviera.org.uk)
3
+ #
4
+ # inspired by elliots fascination with the us
5
+ # threat level.
6
+ #
7
+ # again a dirty hack but it works, just...
8
+ #
9
+
10
+ require 'uri/common'
11
+
12
+ class ThreatPlugin < Plugin
13
+
14
+ def help(plugin, topic="")
15
+ "threat => prints out the current threat level as reported by http://www.dhs.gov/"
16
+ end
17
+
18
+ def privmsg(m)
19
+ color = ""
20
+ red = "\x0304" # severe
21
+ orange = "\x0307" # high
22
+ yellow = "\x0308" # elevated
23
+ blue = "\x0312" # guarded
24
+ green = "\x0303" # low
25
+ black = "\x0301" # default
26
+
27
+ page = @bot.httputil.get URI.parse("http://www.dhs.gov/dhspublic/")
28
+ if page =~ / <img.*dhs\/images\/dhs-advisory-(.*).gif.*/
29
+ state = $1
30
+ end
31
+ case state
32
+ when "severe"
33
+ color = red
34
+ when "high"
35
+ color = orange
36
+ when "elevated"
37
+ color = yellow
38
+ when "guarded"
39
+ color = blue
40
+ when "low"
41
+ color = green
42
+ else
43
+ color = black
44
+ end
45
+
46
+ m.reply color + "Today " + m.sourcenick + " the threat level is " + state.capitalize
47
+
48
+ return
49
+ end
50
+
51
+ end
52
+ plugin = ThreatPlugin.new
53
+ plugin.register("threat")
54
+
55
+
@@ -0,0 +1,39 @@
1
+ require "rubygems"
2
+ require "shorturl"
3
+
4
+ class TinyURL < Plugin
5
+ include WWW
6
+
7
+ # return a help string when the bot is asked for help on this plugin
8
+ def help(plugin, topic="")
9
+ return "tinyurl <your long url>"
10
+ end
11
+
12
+ # reply to a private message that we've registered for
13
+ def privmsg(m)
14
+
15
+ # m.params contains the rest of the message, m.plugin contains the first
16
+ # word (useful because it's possible to register for multiple commands)
17
+ unless(m.params)
18
+ m.reply "incorrect usage. " + help(m.plugin)
19
+ end
20
+
21
+ # TODO: might want to add a check here to validate the url
22
+ # if they call 'rubyurl help' backwards, don't return a lame link
23
+
24
+ if (m.params == "help")
25
+ m.reply "Try again. Correct usage is: " + help(m.plugin)
26
+ return false
27
+ end
28
+
29
+ # call the ShortURL library with the value of the url
30
+ url = ShortURL.shorten(m.params, :tinyurl)
31
+
32
+ m.reply "tinyurl: #{url}"
33
+
34
+ end
35
+ end
36
+
37
+ # create an instance of the RubyURL class and register it as a plugin
38
+ tinyurl = TinyURL.new
39
+ tinyurl.register("tinyurl")
@@ -0,0 +1,204 @@
1
+ # Author: Giuseppe "Oblomov" Bilotta <giuseppe.bilotta@gmail.com>
2
+ # Add a bunch of topic manipulation features
3
+
4
+ class TopicPlugin < Plugin
5
+ def initialize
6
+ super
7
+ @separator = "|" # default separator
8
+ end
9
+
10
+ def help(plugin, topic="")
11
+ case plugin
12
+ when "topic"
13
+ case topic
14
+ when "add"
15
+ return "topic add <text> => add <text> at the end the topic"
16
+ when "prepend"
17
+ return "topic prepend <text> => add <text> at the beginning of the topic"
18
+ when "addat"
19
+ return "topic addat <num> <text> => add <text> at position <num> of the topic"
20
+ when "del", "delete"
21
+ return "topic del <num> => remove section <num> from the topic"
22
+ when "replace"
23
+ return "topic replace <num> <text> => Replaces section <num> with <text>"
24
+ when "sep", "separator"
25
+ return "topic sep(arator) [<text>] => get or set the topic section separator"
26
+ when "learn"
27
+ return "topic learn => remembers the topic for later"
28
+ when "restore"
29
+ return "topic restore => resets the topic to the latest remembered one"
30
+ when "clear"
31
+ return "topic clear => clears the topic"
32
+ when "set"
33
+ return "topic set <text> => sets the topic to <text>"
34
+ else
35
+ return "topic add(at)|prepend|del(ete)|replace|sep(arator)|learn|restore|clear|set: " + \
36
+ "manipulate the topic of the current channel; use topic <#channel> <command> " + \
37
+ "for private addressing"
38
+ end
39
+ end
40
+ end
41
+
42
+ def handletopic(m, param)
43
+ return unless m.kind_of?(PrivMessage)
44
+ if m.public?
45
+ ch = m.channel.downcase
46
+ else
47
+ ch = param[:channel].downcase
48
+ end
49
+ cmd = param[:command]
50
+ txt = param[:text].join(" ")
51
+
52
+ unless @bot.channels.has_key?(ch)
53
+ m.reply "I am not in channel #{ch}"
54
+ return
55
+ end
56
+
57
+ case cmd
58
+ when /^a(dd|ppend)$/
59
+ topicappend(m, ch, txt)
60
+ when 'prepend'
61
+ topicprepend(m, ch, txt)
62
+ when 'addat'
63
+ if txt =~ /\s*(-?\d+)\s+(.*)\s*/
64
+ num = $1.to_i - 1
65
+ num += 1 if num < 0
66
+ txt = $2
67
+ topicaddat(m, ch, num, txt)
68
+ end
69
+ when /^del(ete)?$/
70
+ if txt =~ /\s*(-?\d+)\s*/
71
+ num=$1.to_i - 1
72
+ num += 1 if num < 0
73
+ topicdel(m, ch, num)
74
+ end
75
+ when 'set'
76
+ topicset(m, ch, txt)
77
+ when 'clear'
78
+ topicset(m, ch, '')
79
+ when /^sep(arator)?$/
80
+ topicsep(m, ch, txt)
81
+ when 'learn'
82
+ learntopic(m, ch)
83
+ when 'replace'
84
+ if txt =~ /\s*(-?\d+)\s+(.*)\s*/
85
+ num = $1.to_i - 1
86
+ num += 1 if num < 0
87
+ txt = $2
88
+ replacetopic(m, ch, num, txt)
89
+ end
90
+ when 'restore'
91
+ restoretopic(m, ch)
92
+ else
93
+ m.reply 'unknown command'
94
+ end
95
+ end
96
+
97
+ def topicsep(m, ch, txt)
98
+ if txt
99
+ sep = txt.strip
100
+ if sep != ""
101
+ setsep(ch, sep)
102
+ end
103
+ end
104
+ m.reply "Topic separator set to #{getsep(ch)}"
105
+ end
106
+
107
+ def setsep(ch, sep)
108
+ if @registry.has_key?(ch)
109
+ data = @registry[ch]
110
+ else
111
+ data = Hash.new
112
+ end
113
+
114
+ oldsep = getsep(ch)
115
+ topic = @bot.channels[ch].topic.to_s
116
+ topicarray = topic.split(/\s+#{Regexp.escape(oldsep)}\s*/)
117
+
118
+ if sep != oldsep and topicarray.length > 0
119
+ newtopic = topicarray.join(" #{sep} ")
120
+ @bot.topic ch, newtopic
121
+ end
122
+
123
+ data[:separator] = sep
124
+ @registry[ch] = data
125
+ end
126
+
127
+ def getsep(ch)
128
+ if @registry.has_key?(ch)
129
+ if @registry[ch].has_key?(:separator)
130
+ return @registry[ch][:separator]
131
+ end
132
+ end
133
+ return @separator
134
+ end
135
+
136
+ def topicaddat(m, channel, num, txt)
137
+ sep = getsep(channel)
138
+ topic = @bot.channels[channel].topic.to_s
139
+ topicarray = topic.split(/\s+#{Regexp.escape(sep)}\s*/)
140
+ topicarray.insert(num, txt)
141
+ newtopic = topicarray.join(" #{sep} ")
142
+ @bot.topic channel, newtopic
143
+ end
144
+
145
+ def topicappend(m, ch, txt)
146
+ topicaddat(m, ch, -1, txt)
147
+ end
148
+
149
+ def topicprepend(m, ch, txt)
150
+ topicaddat(m, ch, 0, txt)
151
+ end
152
+
153
+ def topicdel(m, channel, num)
154
+ sep = getsep(channel)
155
+ topic = @bot.channels[channel].topic.to_s
156
+ topicarray = topic.split(/\s+#{Regexp.escape(sep)}\s*/)
157
+ topicarray.delete_at(num)
158
+ newtopic = topicarray.join(" #{sep} ")
159
+ @bot.topic channel, newtopic
160
+ end
161
+
162
+ def learntopic(m, channel)
163
+ return if !@bot.auth.allow?("learntopic", m.source, m.replyto)
164
+ topic = @bot.channels[channel].topic.to_s
165
+ if @registry.has_key?(channel)
166
+ data = @registry[channel]
167
+ else
168
+ data = Hash.new
169
+ end
170
+ data[:topic] = topic
171
+ @registry[channel] = data
172
+ m.okay
173
+ end
174
+
175
+ def replacetopic(m, channel, num, txt)
176
+ return if !@bot.auth.allow?("topic", m.source, m.replyto)
177
+ sep = getsep(channel)
178
+ topic = @bot.channels[channel].topic.to_s
179
+ topicarray = topic.split(/\s+#{Regexp.escape(sep)}\s*/)
180
+ topicarray[num] = txt
181
+ newtopic = topicarray.join(" #{sep} ")
182
+ @bot.topic channel, newtopic
183
+ end
184
+
185
+ def restoretopic(m, channel)
186
+ return if !@bot.auth.allow?("restoretopic", m.source, m.replyto)
187
+ if @registry.has_key?(channel) && @registry[channel].has_key?(:topic)
188
+ topic = @registry[channel][:topic]
189
+ @bot.topic channel, topic
190
+ else
191
+ m.reply "I don't remember any topic for this channel"
192
+ end
193
+ end
194
+
195
+ def topicset(m, channel, text)
196
+ return if !@bot.auth.allow?("topic", m.source, m.replyto)
197
+ @bot.topic channel, text
198
+ end
199
+
200
+ end
201
+ plugin = TopicPlugin.new
202
+ plugin.map 'topic :command *text', :action => 'handletopic', :public => true, :private => false
203
+ plugin.map 'topic :channel :command *text', :action => 'handletopic', :public => false, :private => true
204
+