comboy-autumn 3.1

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 (81) hide show
  1. data/README.textile +1192 -0
  2. data/autumn.gemspec +25 -0
  3. data/bin/autumn +27 -0
  4. data/lib/autumn.rb +2 -0
  5. data/lib/autumn/authentication.rb +290 -0
  6. data/lib/autumn/channel_leaf.rb +107 -0
  7. data/lib/autumn/coder.rb +166 -0
  8. data/lib/autumn/console_boot.rb +9 -0
  9. data/lib/autumn/ctcp.rb +250 -0
  10. data/lib/autumn/daemon.rb +207 -0
  11. data/lib/autumn/datamapper_hacks.rb +290 -0
  12. data/lib/autumn/foliater.rb +231 -0
  13. data/lib/autumn/formatting.rb +236 -0
  14. data/lib/autumn/generator.rb +231 -0
  15. data/lib/autumn/genesis.rb +191 -0
  16. data/lib/autumn/inheritable_attributes.rb +162 -0
  17. data/lib/autumn/leaf.rb +738 -0
  18. data/lib/autumn/log_facade.rb +49 -0
  19. data/lib/autumn/misc.rb +87 -0
  20. data/lib/autumn/script.rb +74 -0
  21. data/lib/autumn/speciator.rb +165 -0
  22. data/lib/autumn/stem.rb +919 -0
  23. data/lib/autumn/stem_facade.rb +176 -0
  24. data/resources/daemons/Anothernet.yml +3 -0
  25. data/resources/daemons/AustHex.yml +29 -0
  26. data/resources/daemons/Bahamut.yml +67 -0
  27. data/resources/daemons/Dancer.yml +3 -0
  28. data/resources/daemons/GameSurge.yml +3 -0
  29. data/resources/daemons/IRCnet.yml +3 -0
  30. data/resources/daemons/Ithildin.yml +7 -0
  31. data/resources/daemons/KineIRCd.yml +56 -0
  32. data/resources/daemons/PTlink.yml +6 -0
  33. data/resources/daemons/QuakeNet.yml +20 -0
  34. data/resources/daemons/RFC1459.yml +158 -0
  35. data/resources/daemons/RFC2811.yml +16 -0
  36. data/resources/daemons/RFC2812.yml +36 -0
  37. data/resources/daemons/RatBox.yml +25 -0
  38. data/resources/daemons/Ultimate.yml +24 -0
  39. data/resources/daemons/Undernet.yml +6 -0
  40. data/resources/daemons/Unreal.yml +110 -0
  41. data/resources/daemons/_Other.yml +7 -0
  42. data/resources/daemons/aircd.yml +33 -0
  43. data/resources/daemons/bdq-ircd.yml +3 -0
  44. data/resources/daemons/hybrid.yml +38 -0
  45. data/resources/daemons/ircu.yml +67 -0
  46. data/resources/daemons/tr-ircd.yml +8 -0
  47. data/skel/Rakefile +135 -0
  48. data/skel/config/global.yml +2 -0
  49. data/skel/config/seasons/testing/database.yml +7 -0
  50. data/skel/config/seasons/testing/leaves.yml +7 -0
  51. data/skel/config/seasons/testing/season.yml +2 -0
  52. data/skel/config/seasons/testing/stems.yml +9 -0
  53. data/skel/leaves/administrator/README +20 -0
  54. data/skel/leaves/administrator/controller.rb +67 -0
  55. data/skel/leaves/administrator/views/autumn.txt.erb +1 -0
  56. data/skel/leaves/administrator/views/reload.txt.erb +11 -0
  57. data/skel/leaves/insulter/README +17 -0
  58. data/skel/leaves/insulter/controller.rb +65 -0
  59. data/skel/leaves/insulter/views/about.txt.erb +1 -0
  60. data/skel/leaves/insulter/views/help.txt.erb +1 -0
  61. data/skel/leaves/insulter/views/insult.txt.erb +1 -0
  62. data/skel/leaves/scorekeeper/README +34 -0
  63. data/skel/leaves/scorekeeper/config.yml +2 -0
  64. data/skel/leaves/scorekeeper/controller.rb +104 -0
  65. data/skel/leaves/scorekeeper/helpers/general.rb +64 -0
  66. data/skel/leaves/scorekeeper/models/channel.rb +12 -0
  67. data/skel/leaves/scorekeeper/models/person.rb +14 -0
  68. data/skel/leaves/scorekeeper/models/pseudonym.rb +11 -0
  69. data/skel/leaves/scorekeeper/models/score.rb +14 -0
  70. data/skel/leaves/scorekeeper/tasks/stats.rake +17 -0
  71. data/skel/leaves/scorekeeper/views/about.txt.erb +1 -0
  72. data/skel/leaves/scorekeeper/views/change.txt.erb +5 -0
  73. data/skel/leaves/scorekeeper/views/history.txt.erb +11 -0
  74. data/skel/leaves/scorekeeper/views/points.txt.erb +5 -0
  75. data/skel/leaves/scorekeeper/views/usage.txt.erb +1 -0
  76. data/skel/script/console +34 -0
  77. data/skel/script/daemon +29 -0
  78. data/skel/script/destroy +48 -0
  79. data/skel/script/generate +48 -0
  80. data/skel/script/server +15 -0
  81. metadata +170 -0
@@ -0,0 +1,2 @@
1
+ ---
2
+ season: testing
@@ -0,0 +1,7 @@
1
+ ---
2
+ Example:
3
+ username: root
4
+ adapter: mysql
5
+ host: localhost
6
+ database: example_database
7
+ password: ""
@@ -0,0 +1,7 @@
1
+ ---
2
+ Administrator:
3
+ authentication:
4
+ type: op
5
+ class: Administrator
6
+ Insulter:
7
+ class: Insulter
@@ -0,0 +1,2 @@
1
+ ---
2
+ logging: debug
@@ -0,0 +1,9 @@
1
+ ---
2
+ Example:
3
+ nick: MyIRCBot
4
+ leaves:
5
+ - Administrator
6
+ - Insulter
7
+ rejoin: true
8
+ channel: "#yourchannel"
9
+ server: irc.yourircserver.com
@@ -0,0 +1,20 @@
1
+ = Administrator: An Autumn Leaf
2
+
3
+ <b>Version 1.0 (Jul 8, 2008)</b>
4
+
5
+ Author:: Tim Morgan (mailto:riscfuture@gmail.com)
6
+ Copyright:: Copyright (c)2008 Tim Morgan
7
+ License:: Distributed under the same terms as Ruby.
8
+
9
+ This leaf allows the owner of the IRC bot to perform administrative commands on
10
+ the bot, such as quitting or reloading it. In order to protect such commands
11
+ from abuse, this bot uses the Authenticator module. The Authenticator method
12
+ that is used is specified by the +authentication+ option. For more information,
13
+ see the *Authentication* section of the README.
14
+
15
+ == Usage
16
+
17
+ !autumn:: Displays information about the version of Autumn that is running this
18
+ leaf (unprotected command).
19
+ !quit:: Terminates the stem on which the message was received.
20
+ !reload:: Reloads all source files of all leaves, and all their view files.
@@ -0,0 +1,67 @@
1
+ # Controller for the Administrator leaf.
2
+
3
+ class Controller < Autumn::Leaf
4
+
5
+ # Typing this command reloads all source code for all leaves and support
6
+ # files, allowing you to make "on-the-fly" changes without restarting the
7
+ # process. It does this by reloading the source files defining the classes.
8
+ #
9
+ # If you supply the configuration name of a leaf, only that leaf is reloaded.
10
+ #
11
+ # This command does not reload the YAML configuration files, only the source
12
+ # code.
13
+
14
+ def reload_command(stem, sender, reply_to, msg)
15
+ var :leaves => Hash.new
16
+ if msg then
17
+ if Foliater.instance.leaves.include?(msg) then
18
+ begin
19
+ Foliater.instance.hot_reload Foliater.instance.leaves[msg]
20
+ rescue
21
+ logger.error "Error when reloading #{msg}:"
22
+ logger.error $!
23
+ var(:leaves)[msg] = $!.to_s
24
+ else
25
+ var(:leaves)[msg] = false
26
+ end
27
+ logger.info "#{msg}: Reloaded"
28
+ else
29
+ var :not_found => msg
30
+ end
31
+ else
32
+ Foliater.instance.leaves.each do |name, leaf|
33
+ begin
34
+ Foliater.instance.hot_reload leaf
35
+ rescue
36
+ logger.error "Error when reloading #{name}:"
37
+ logger.error $!
38
+ var(:leaves)[name] = $!.to_s
39
+ else
40
+ var(:leaves)[name] = false
41
+ end
42
+ logger.info "#{name}: Reloaded"
43
+ end
44
+ end
45
+ end
46
+ ann :reload_command, :protected => true
47
+
48
+ # Typing this command will cause the Stem to exit.
49
+
50
+ def quit_command(stem, sender, reply_to, msg)
51
+ stem.quit
52
+ end
53
+ ann :quit_command, :protected => true
54
+
55
+ # Typing this command will display information about the version of Autumn
56
+ # that is running this leaf.
57
+
58
+ def autumn_command(stem, sender, reply_to, msg)
59
+ var :version => AUTUMN_VERSION
60
+ end
61
+
62
+ # Suppress the !commands command; don't want to publicize the administrative
63
+ # features.
64
+
65
+ def commands_command(stem, sender, reply_to, msg)
66
+ end
67
+ end
@@ -0,0 +1 @@
1
+ Autumn version <%= var :version %>, an IRC bot framework for Ruby (http://github.com/RISCfuture/autumn).
@@ -0,0 +1,11 @@
1
+ <% if var(:not_found) %>
2
+ There is no leaf named <%= var :not_found %>.
3
+ <% else %>
4
+ <% var(:leaves).each do |leaf, error| %>
5
+ <% if error %>
6
+ <%= leaf %> couldn't be reloaded: <%= error %>
7
+ <% else %>
8
+ <%= leaf %> was reloaded successfully.
9
+ <% end %>
10
+ <% end %>
11
+ <% end %>
@@ -0,0 +1,17 @@
1
+ = Insulter: An Autumn Leaf
2
+
3
+ <b>Version 1.0 (Jul 4, 2008)</b>
4
+
5
+ Author:: Tim Morgan (mailto:riscfuture@gmail.com)
6
+ Copyright:: Copyright (c)2008 Tim Morgan
7
+ License:: Distributed under the same terms as Ruby. Portions of this content
8
+ are copyright (c)1996 Main Strike Telecommunications, Inc.
9
+
10
+ A simple Autumn Leaf that generates faux-Shakespearean insults. This leaf
11
+ required no database and no additional gems beyond that of a normal Autumn
12
+ install.
13
+
14
+ == Usage
15
+
16
+ !insult [name]:: The bot lets fly a barbarous insult against [name], whose very
17
+ spirit will thenceforth be crushed into a negligible pulp.
@@ -0,0 +1,65 @@
1
+ # Controller and model for the Insulter leaf; maintains the list of insult
2
+ # substrings and chooses from them randomly.
3
+
4
+ class Controller < Autumn::Leaf
5
+
6
+ # Insults the unfortunate argument of this command.
7
+
8
+ def insult_command(stem, sender, reply_to, msg)
9
+ if msg.nil? then render :help
10
+ else insult msg.capitalize end
11
+ end
12
+
13
+ # Displays information about the leaf.
14
+
15
+ def about_command(stem, sender, reply_to, msg)
16
+ end
17
+
18
+ private
19
+
20
+ ADJECTIVES = [
21
+ 'an artless', 'a bawdy', 'a beslubbering', 'a bootless', 'a churlish',
22
+ 'a clouted', 'a cockered', 'a craven', 'a currish', 'a dankish',
23
+ 'a dissembling', 'a droning', 'an errant', 'a fawning', 'a fobbing',
24
+ 'a frothy', 'a froward', 'a gleeking', 'a goatish', 'a gorbellied',
25
+ 'an impertinent', 'an infectious', 'a jarring', 'a loggerheaded',
26
+ 'a lumpish', 'a mammering', 'a mangled', 'a mewling', 'a paunchy',
27
+ 'a pribbling', 'a puking', 'a puny', 'a qualling', 'a rank', 'a reeky',
28
+ 'a roguish', 'a ruttish', 'a saucy', 'a spleeny', 'a spongy', 'a surly',
29
+ 'a tottering', 'an unmuzzled', 'a vain', 'a venomed', 'a villainous',
30
+ 'a warped', 'a wayward', 'a weedy', 'a yeasty'
31
+ ]
32
+
33
+ PARTICIPLES = [
34
+ 'base-court', 'bat-fowling', 'beef-witted', 'beetle-headed', 'boil-brained',
35
+ 'clapper-clawed', 'clay-brained', 'common-kissing', 'crook-pated',
36
+ 'dismal-dreaming', 'dizzy-eyed', 'doghearted', 'dread-bolted',
37
+ 'earth-vexing', 'elf-skinned', 'fat-kidneyed', 'fen-sucked', 'flap-mouthed',
38
+ 'fly-bitten', 'folly-fallen', 'fool-born', 'full-gorged', 'guts-griping',
39
+ 'half-faced', 'hasty-witted', 'hedge-born', 'hell-hated', 'idle-headed',
40
+ 'ill-breeding', 'ill-nurtured', 'knotty-pated', 'milk-livered',
41
+ 'motley-minded', 'onion-eyed', 'plume-plucked', 'pottle-deep', 'pox-marked',
42
+ 'reeling-ripe', 'rough-hewn', 'rude-growing', 'rump-fed', 'shard-borne',
43
+ 'sheep-biting', 'spur-galled', 'swag-bellied', 'tardy-gaited',
44
+ 'tickle-brained', 'toad-spotted', 'urchin-snouted', 'weather-bitten'
45
+ ]
46
+
47
+ NOUNS = [
48
+ 'apple-john', 'baggage', 'barnacle', 'bladder', 'boar-pig', 'bugbear',
49
+ 'bum-bailey', 'canker-blossom', 'clack-dish', 'clotpole', 'codpiece',
50
+ 'coxcomb', 'death-token', 'dewberry', 'flap-dragon', 'flax-wench',
51
+ 'flirt-gill', 'foot-licker', 'fustilarian', 'giglet', 'gudgeon', 'haggard',
52
+ 'harpy', 'hedge-pig', 'horn-beast', 'hugger-mugger', 'joithead', 'lewdster',
53
+ 'lout', 'maggot-pie', 'malt-worm', 'mammet', 'measle', 'minnow',
54
+ 'miscreant', 'moldwarp', 'mumble-news', 'nut-hook', 'pigeon-egg', 'pignut',
55
+ 'pumpion', 'puttock', 'ratsbane', 'scut', 'skainsmate', 'strumpet',
56
+ 'varlet', 'vassal', 'wagtail', 'whey-face'
57
+ ]
58
+
59
+ def insult(victim)
60
+ var :adjective => ADJECTIVES.pick
61
+ var :participle => PARTICIPLES.pick
62
+ var :noun => NOUNS.pick
63
+ var :victim => victim
64
+ end
65
+ end
@@ -0,0 +1 @@
1
+ Insulter version 1.0 (7-4-08) by Tim Morgan: An Autumn Leaf. Insults copyright (c)1996 Main Strike Telecommunications, Inc.
@@ -0,0 +1 @@
1
+ Type "!insult Ted" to crush Ted's spirit with a devastating insult.
@@ -0,0 +1 @@
1
+ <%= var :victim %>, thou art <%= var :adjective %> <%= var :participle %> <%= var :noun %>!
@@ -0,0 +1,34 @@
1
+ = Scorekeeper: An Autumn Leaf
2
+
3
+ <b>Version 3.0 (Jul 4, 2008)</b>
4
+
5
+ Author:: Tim Morgan (mailto:riscfuture@gmail.com)
6
+ Copyright:: Copyright (c)2007-2008 Tim Morgan
7
+ License:: Distributed under the same terms as Ruby.
8
+
9
+ An Autumn Leaf used for an in-channel scorekeeping system. This can operate both
10
+ as an open or closed score system. (In the former, new members are automatically
11
+ added when they receive points; in the latter, only authorized members can give
12
+ and receive points.)
13
+
14
+ Scorekeeper is a database-backed leaf. It requires the DataMapper gem
15
+ (http://www.datamapper.org) in order to run. The database stores channels and
16
+ their members, and each member's point history.
17
+
18
+ Scorekeeper supports pseudonyms. Entries in the +pseudonyms+ table can be used
19
+ to help ensure that the correct person's points are changed even when the sender
20
+ uses a nickname or abbreviation.
21
+
22
+ Scorekeeper takes one custom configuration option, +scoring+, which can be
23
+ either "open" or "closed". A closed system only allows a specified set of users
24
+ to receive and give points. An open system allows anyone to award points to
25
+ anyone.
26
+
27
+ == Usage
28
+
29
+ !points [name]:: Get a person's score
30
+ !points [name] [+|-][number] [reason]:: Change a person's score (you must have a
31
+ "+" or a "-"). A reason is optional.
32
+ !points [name] history:: Return some recent history of that person's score.
33
+ !points [name] history [time period]:: Selects history from a time period.
34
+ !points [name] history [sender]:: Selects point changes from a sender.
@@ -0,0 +1,2 @@
1
+ ---
2
+ scoring: open
@@ -0,0 +1,104 @@
1
+ require 'dm-ar-finders'
2
+
3
+ begin
4
+ gem 'chronic'
5
+ require 'chronic'
6
+ rescue Gem::LoadError
7
+ # Install the "chronic" gem for more robust date parsing
8
+ end
9
+
10
+ # Controller for the Scorekeeper leaf. This class contains only the methods
11
+ # directly relating to IRC. Other methods are stored in the helper and model
12
+ # classes.
13
+
14
+ class Controller < Autumn::Leaf
15
+
16
+ # Displays an about message.
17
+
18
+ def about_command(stem, sender, reply_to, msg)
19
+ end
20
+
21
+ # Displays the current point totals, or modifies someone's score, depending on
22
+ # the message provided with the command.
23
+
24
+ def points_command(stem, sender, reply_to, msg)
25
+ if msg.nil? or msg.empty? then
26
+ var :totals => totals(stem, reply_to)
27
+ elsif msg =~ /^(\w+)\s+history\s*(.*)$/ then
28
+ parse_history stem, reply_to, $1, $2
29
+ render :history
30
+ elsif msg =~ /^(\w+)\s+([\+\-]\d+)\s*(.*)$/ then
31
+ parse_change stem, reply_to, sender, $1, $2.to_i, $3
32
+ render :change
33
+ else
34
+ render :usage
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def points(stem, channel)
41
+ chan = Channel.find_or_create :server => server_identifier(stem), :name => channel
42
+ scores = chan.scores.all
43
+ scores.inject(Hash.new(0)) { |hsh, score| hsh[score.receiver.name] += score.change; hsh }
44
+ end
45
+
46
+ def totals(stem, channel)
47
+ points(stem, channel).sort { |a,b| b.last <=> a.last }
48
+ end
49
+
50
+ def parse_change(stem, channel, sender, victim, delta, note)
51
+ giver = find_person(stem, sender[:nick])
52
+ receiver = find_person(stem, victim)
53
+ if giver.nil? and options[:scoring] == 'open' then
54
+ giver ||= Person.create :server => server_identifier(stem), :name => sender[:nick]
55
+ end
56
+ if receiver.nil? and options[:scoring] == 'open' then
57
+ receiver ||= Person.create :server => server_identifier(stem), :name => find_in_channel(stem, channel, victim)
58
+ end
59
+ unless authorized?(giver, receiver)
60
+ var :unauthorized => true
61
+ var :receiver => receiver.nil? ? victim : receiver.name
62
+ return
63
+ end
64
+ change_points stem, channel, giver, receiver, delta, note
65
+ var :giver => giver
66
+ var :receiver => receiver
67
+ var :delta => delta
68
+ end
69
+
70
+ def parse_history(stem, channel, subject, argument)
71
+ date = argument.empty? ? nil : parse_date(argument)
72
+ scores = Array.new
73
+
74
+ chan = Channel.first(:name => channel)
75
+ person = find_person(stem, subject)
76
+ if person.nil? then
77
+ var :person => subject
78
+ var :no_history => true
79
+ return
80
+ end
81
+
82
+ if date then
83
+ start, stop = find_range(date)
84
+ scores = chan.scores.all(:conditions => [ "receiver_id = ? AND created_at >= ? AND created_at < ?", person.id, start, stop ], :order => [ :created_at.desc ], :limit => 5)
85
+ #TODO is there a way to scope by both channel and receiver?
86
+ elsif argument.empty? then
87
+ scores = chan.scores.all(:conditions => [ "receiver_id = ?", person.id ], :order => [ :created_at.desc ], :limit => 5)
88
+ #TODO is there a way to scope by both channel and receiver?
89
+ else
90
+ giver = find_person(stem, argument)
91
+ if giver.nil? then
92
+ var :giver => argument
93
+ var :receiver => person
94
+ var :no_giver_history => true
95
+ return
96
+ end
97
+ scores = chan.scores.all(:conditions => [ "receiver_id = ? AND giver_id = ?", person.id, giver.id ], :order => [ :created_at.desc ], :limit => 5)
98
+ #TODO is there a way to scope by channel, receiver, and giver?
99
+ end
100
+ var :receiver => person
101
+ var :giver => giver
102
+ var :scores => scores
103
+ end
104
+ end
@@ -0,0 +1,64 @@
1
+ # Utility methods used by Scorekeeper.
2
+
3
+ module GeneralHelper
4
+ def parse_date(str)
5
+ date = nil
6
+ begin
7
+ date = Chronic.parse(str, :context => :past, :guess => false)
8
+ rescue NameError
9
+ begin
10
+ date = Date.parse(str)
11
+ rescue ArgumentError
12
+ end
13
+ end
14
+ return date
15
+ end
16
+
17
+ def find_range(date)
18
+ start = nil
19
+ stop = nil
20
+ if date.kind_of? Range then
21
+ start = date.first
22
+ stop = date.last
23
+ elsif date.kind_of? Time then
24
+ start = date.to_date
25
+ stop = date.to_date + 1
26
+ else
27
+ start = date
28
+ stop = date + 1
29
+ end
30
+ return start, stop
31
+ end
32
+
33
+ def find_person(stem, nick)
34
+ Person.all(:server => server_identifier(stem)).each do |person|
35
+ return person if person.name.downcase == normalize(nick) or person.pseudonyms.collect { |pn| pn.name.downcase }.include? normalize(nick)
36
+ end
37
+ return nil
38
+ end
39
+
40
+ def find_in_channel(stem, channel, victim)
41
+ stem.channel_members[channel].each do |name, privilege|
42
+ return normalize(name, false) if normalize(name) == normalize(victim)
43
+ end
44
+ return victim
45
+ end
46
+
47
+ def normalize(nick, dc=true)
48
+ dc ? nick.downcase.split(/\|/)[0] : nick.split(/\|/)[0]
49
+ end
50
+
51
+ def authorized?(giver, receiver)
52
+ giver and receiver and giver.authorized? and giver.name != receiver.name
53
+ end
54
+
55
+ def change_points(stem, channel, giver, receiver, delta, note=nil)
56
+ return if delta.zero?
57
+ chan = Channel.find_or_create :server => server_identifier(stem), :name => channel
58
+ chan.scores.create :giver => giver, :receiver => receiver, :change => delta, :note => note
59
+ end
60
+
61
+ def server_identifier(stem)
62
+ "#{stem.server}:#{stem.port}"
63
+ end
64
+ end