erasmus 0.0.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.
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
2
+ Version 2, December 2004
3
+
4
+ Copyright (C) 2004 Sam Hocevar
5
+ 14 rue de Plaisance, 75014 Paris, France
6
+ Everyone is permitted to copy and distribute verbatim or modified
7
+ copies of this license document, and changing it is allowed as long
8
+ as the name is changed.
9
+
10
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
11
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
12
+
13
+ 0. You just DO WHAT THE FUCK YOU WANT TO.
data/README.rdoc ADDED
@@ -0,0 +1,18 @@
1
+ = erasmus
2
+
3
+ A simple, modular irc bot/framework.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but
13
+ bump version in a commit by itself I can ignore when I pull)
14
+ * Send me a pull request. Bonus points for topic branches.
15
+
16
+ == Copyright
17
+
18
+ Copyright (c) 2009 xiongchiamiov. See LICENSE for details.
data/lib/bots.rb ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'erasmus'
4
+ require 'utils'
5
+
6
+ Erasmus::Bot.new("irc.freenode.net").join([
7
+ Erasmus::Channel.new('erasmus-testing') \
8
+ .extend(Utils::Foo) \
9
+ .extend(Utils::Changelog) \
10
+ .extend(Utils::FlagFloodProtection), \
11
+ Erasmus::Channel.new('erasmus-testing2'),
12
+ ]).run
data/lib/erasmus.rb ADDED
@@ -0,0 +1,162 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'socket'
4
+
5
+ module Erasmus
6
+ class Bot
7
+ attr_reader :nick
8
+
9
+ def initialize(server, port=6667)
10
+ @nick = 'mpu_test'
11
+ @channels = {}
12
+ @socket = TCPSocket.open(server, port)
13
+ say "NICK #{@nick}"
14
+ say "USER #{@nick} 0 * #{@nick}"
15
+ end
16
+
17
+ def join(channels)
18
+ channels.each do |channel|
19
+ channel.server = self
20
+ channel.join
21
+ @channels[channel.name] = channel
22
+ end
23
+
24
+ #return self so we can chain methods
25
+ self
26
+ end
27
+
28
+ def say(msg)
29
+ puts msg
30
+ @socket.puts msg
31
+ end
32
+
33
+ def say_to_channel(channel, message)
34
+ say "PRIVMSG ##{channel} :#{message}"
35
+ end
36
+
37
+ def pm_user(user, message)
38
+ say "PRIVMSG #{user} :#{message}"
39
+ end
40
+
41
+ def notice_user(user, message)
42
+ say "NOTICE #{user} :#{message}"
43
+ end
44
+
45
+ def notice_channel(channel, message)
46
+ say "NOTICE ##{channel} :#{message}"
47
+ end
48
+
49
+ def run
50
+ until @socket.eof? do
51
+ msg = @socket.gets
52
+ puts msg
53
+
54
+ case msg
55
+ when /^PING :(.*)$/
56
+ say "PONG #{$1}"
57
+ # channel messages
58
+ when /^:(.*)!(.*) PRIVMSG #(\S+) :(.*)$/
59
+ user = $1
60
+ host = $2
61
+ channel = $3
62
+ content = $4
63
+ @channels[channel].handle_public_message(user, host, content)
64
+ # actual private messages
65
+ when /^:(.*)!(.*) PRIVMSG \S+ :(.*)$/
66
+ user = $1
67
+ host = $2
68
+ content = $3
69
+ handle_private_message(user, host, content)
70
+ end
71
+ end
72
+ end
73
+
74
+ def handle_private_message(user, host, message)
75
+ pm_user(user, 'hey!')
76
+ end
77
+
78
+ def quit
79
+ @channels.each do |name, channel|
80
+ channel.part
81
+ end
82
+ say 'QUIT'
83
+ end
84
+ end
85
+
86
+ class Channel
87
+ attr_accessor :server
88
+ attr_reader :name
89
+
90
+ def initialize(channel, flag='!')
91
+ @name = channel
92
+ @flag = flag
93
+
94
+ @flags = {}
95
+ @blacklists = []
96
+ end
97
+
98
+ def join
99
+ @server.say "JOIN ##{@name}"
100
+ end
101
+
102
+ def part(message='Bai~')
103
+ @server.say "PART ##{@name} :#{message}"
104
+ end
105
+
106
+ def say(message)
107
+ @server.say_to_channel(@name, message)
108
+ end
109
+
110
+ def hilight_user(user, message)
111
+ @server.say_to_channel(@name, "#{user}: #{message}")
112
+ end
113
+
114
+ def notice_user(user, message)
115
+ @server.notice_user(user, message)
116
+ end
117
+
118
+ def notice_channel(message)
119
+ @server.notice_channel(@name, message)
120
+ end
121
+
122
+ def handle_public_message(user, host, message)
123
+ if message =~ /^#{@server.nick}: (.*)$/
124
+ handle_hilight(user, host, $1)
125
+ elsif message =~ /^#{@flag}(\S+)\s(.*)$/
126
+ command = $1
127
+ arguments = $2.split(/\s/)
128
+ handle_flag(user, host, command, arguments)
129
+ end
130
+ end
131
+
132
+ def handle_hilight(user, host, message)
133
+ end
134
+ def handle_flag(user, host, flag, arguments)
135
+ if allowed? user
136
+ begin
137
+ @flags[flag].call(user, host, arguments)
138
+ rescue NoMethodError
139
+ #say("Sorry, there's no action associated with the flag #{flag}.")
140
+ end
141
+ end
142
+ end
143
+
144
+ def allowed?(user)
145
+ begin
146
+ @blacklists.each do |blacklist|
147
+ blacklist.call(user)
148
+ end
149
+ rescue NotAllowedException
150
+ return false
151
+ rescue => detail
152
+ say("Uh oh: #{detail}")
153
+ return false
154
+ else
155
+ return true
156
+ end
157
+ end
158
+ end
159
+
160
+ class NotAllowedException < StandardError
161
+ end
162
+ end
data/lib/utils.rb ADDED
@@ -0,0 +1,69 @@
1
+ module Utils
2
+ module Foo
3
+ def handle_hilight(user, host, message)
4
+ hilight_user(user, 'whatcha want?')
5
+ end
6
+
7
+ def self.extended(obj)
8
+ obj.instance_eval {
9
+ @flags['foo'] = lambda { |user, host, arguments|
10
+ say('bar')
11
+ }
12
+ @flags['bar'] = lambda { |user, host, arguments|
13
+ notice_user(user, 'baz')
14
+ }
15
+ @flags['baz'] = lambda { |user, host, arguments|
16
+ notice_channel('not baz!')
17
+ }
18
+ }
19
+ end
20
+
21
+ def join
22
+ @server.say "JOIN ##{@name}"
23
+ say "#{1.chr}ACTION is here to help#{1.chr}"
24
+ end
25
+ end
26
+
27
+ module Changelog
28
+ def self.extended(obj)
29
+ obj.instance_eval {
30
+ @flags['changelog'] = lambda { |user, host, arguments|
31
+ if arguments[0] and arguments[0] =~ /^[\w\d "]+$/
32
+ output = `git --no-pager log --pretty=format:%s --since=#{arguments[0]}`
33
+ else
34
+ output = `git --no-pager log --pretty=format:%s -1`
35
+ end
36
+ if output.empty?
37
+ say "No changes found for specified period of time."
38
+ else
39
+ for summary in output.split("\n")
40
+ say summary
41
+ end
42
+ end
43
+ }
44
+ }
45
+ end
46
+ end
47
+
48
+ module FlagFloodProtection
49
+ require 'erasmus'
50
+ require 'thread' # for Queue
51
+
52
+ def self.extended(obj)
53
+ obj.instance_eval {
54
+ @userMessages = Hash.new(Queue.new)
55
+ @blacklists << lambda { |user|
56
+ @userMessages[user] << Time.now
57
+
58
+ # don't allow messages from users who have sent
59
+ # 5 messages in 15 seconds
60
+ if @userMessages[user].length > 4 \
61
+ and Time.now - @userMessages[user].pop < 15
62
+ say("#{user} is flooding!")
63
+ raise Erasmus::NotAllowedException
64
+ end
65
+ }
66
+ }
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class ErasmusTest < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'erasmus'
8
+
9
+ class Test::Unit::TestCase
10
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: erasmus
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - xiongchiamiov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-15 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: thoughtbot-shoulda
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description: "TODO: longer description of your gem"
26
+ email: xiong.chiamiov@gmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - LICENSE
33
+ - README.rdoc
34
+ files:
35
+ - lib/bots.rb
36
+ - lib/erasmus.rb
37
+ - lib/utils.rb
38
+ - LICENSE
39
+ - README.rdoc
40
+ has_rdoc: true
41
+ homepage: http://github.com/xiongchiamiov/erasmus
42
+ post_install_message:
43
+ rdoc_options:
44
+ - --charset=UTF-8
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ requirements: []
60
+
61
+ rubyforge_project:
62
+ rubygems_version: 1.3.1
63
+ signing_key:
64
+ specification_version: 2
65
+ summary: A simple, modular irc bot/framework
66
+ test_files:
67
+ - test/erasmus_test.rb
68
+ - test/test_helper.rb