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 +13 -0
- data/README.rdoc +18 -0
- data/lib/bots.rb +12 -0
- data/lib/erasmus.rb +162 -0
- data/lib/utils.rb +69 -0
- data/test/erasmus_test.rb +7 -0
- data/test/test_helper.rb +10 -0
- metadata +68 -0
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
|
data/test/test_helper.rb
ADDED
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
|