blur 1.8.6 → 2.1.6
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.
- checksums.yaml +5 -5
- data/README.md +10 -24
- data/executables/blur +63 -0
- data/library/blur/callbacks.rb +53 -0
- data/library/blur/channel.rb +78 -0
- data/library/blur/client.rb +165 -107
- data/library/blur/handling.rb +259 -179
- data/library/blur/network/connection.rb +26 -30
- data/library/blur/network/isupport.rb +38 -32
- data/library/blur/network.rb +193 -55
- data/library/blur/script.rb +132 -116
- data/library/blur/script_cache.rb +45 -0
- data/library/blur/user.rb +122 -0
- data/library/blur/version.rb +3 -3
- data/library/blur.rb +46 -19
- metadata +35 -28
- data/library/blur/encryption/base64.rb +0 -71
- data/library/blur/encryption/fish.rb +0 -80
- data/library/blur/encryption.rb +0 -17
- data/library/blur/enhancements.rb +0 -41
- data/library/blur/evaluable.rb +0 -13
- data/library/blur/extension.rb +0 -42
- data/library/blur/network/channel.rb +0 -91
- data/library/blur/network/command.rb +0 -83
- data/library/blur/network/user.rb +0 -106
- data/library/blur/script/cache.rb +0 -77
- data/library/blur/script/commands.rb +0 -77
- data/library/blur/script/dsl.rb +0 -52
@@ -1,71 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Blur
|
4
|
-
module Encryption
|
5
|
-
# The +Encryption::Base64+ module differs from the original Base64
|
6
|
-
# implementation. I'm not sure how exactly, perhaps the charset?
|
7
|
-
#
|
8
|
-
# I originally found the Ruby implementation of FiSH on a website where
|
9
|
-
# it was graciously submitted by an anonymous user, since then I've
|
10
|
-
# implemented it in a weechat script, and now I've refactored it for use in
|
11
|
-
# Blur.
|
12
|
-
#
|
13
|
-
# @see http://maero.dk/pub/sources/weechat/ruby/autoload/fish.rb
|
14
|
-
module Base64
|
15
|
-
# The difference I suspect between the original Base64 implementation
|
16
|
-
# and the one used in FiSH.
|
17
|
-
Charset = "./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
18
|
-
|
19
|
-
# Decode a base64-encoded string.
|
20
|
-
#
|
21
|
-
# @return [String] Base64-decoded string.
|
22
|
-
def self.decode string
|
23
|
-
unless string.length % 12 == 0
|
24
|
-
raise BadInputError, "input has to be a multiple of 12 characters."
|
25
|
-
end
|
26
|
-
|
27
|
-
String.new.tap do |buffer|
|
28
|
-
j = -1
|
29
|
-
|
30
|
-
while j < string.length - 1
|
31
|
-
right, left = 0, 0
|
32
|
-
|
33
|
-
6.times{|i| right |= Charset.index(string[j += 1]) << (i * 6) }
|
34
|
-
6.times{|i| left |= Charset.index(string[j += 1]) << (i * 6) }
|
35
|
-
|
36
|
-
4.times do |i|
|
37
|
-
buffer << ((left & (0xFF << ((3 - i) * 8))) >> ((3 - i) * 8)).chr
|
38
|
-
end
|
39
|
-
|
40
|
-
4.times do |i|
|
41
|
-
buffer << ((right & (0xFF << ((3 - i) * 8))) >> ((3 - i) * 8)).chr
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# Encode a string-cipher.
|
48
|
-
#
|
49
|
-
# @return [String] Base64-encoded string.
|
50
|
-
def self.encode string
|
51
|
-
unless string.length % 8 == 0
|
52
|
-
raise BadInputError, "input has to be a multiple of 8 characters."
|
53
|
-
end
|
54
|
-
|
55
|
-
left = 0
|
56
|
-
right = 0
|
57
|
-
decimals = [24, 16, 8, 0]
|
58
|
-
|
59
|
-
String.new.tap do |buffer|
|
60
|
-
string.each_block do |block|
|
61
|
-
4.times{|i| left += (block[i].ord << decimals[i]) }
|
62
|
-
4.times{|i| right += (block[i+4].ord << decimals[i]) }
|
63
|
-
|
64
|
-
6.times{|i| buffer << Charset[right & 0x3F].chr; right = right >> 6 }
|
65
|
-
6.times{|i| buffer << Charset[left & 0x3F].chr; left = left >> 6 }
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
@@ -1,80 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require 'crypt/blowfish'
|
4
|
-
|
5
|
-
module Blur
|
6
|
-
module Encryption
|
7
|
-
# The +FiSH+ algorithm is a combination of Base64 encoding
|
8
|
-
# and the blowfish encryption.
|
9
|
-
#
|
10
|
-
# Shared text messages are prepended by "++OK+", an older implementation
|
11
|
-
# prepends it with "+mcps+" - Blur drops support for that implementation.
|
12
|
-
#
|
13
|
-
# There's multiple client-implementations available on the official FiSH
|
14
|
-
# homepage.
|
15
|
-
#
|
16
|
-
# == DH1080 Key exchange
|
17
|
-
# The newer FiSH implementation introduces a 1080bit Diffie-Hellman
|
18
|
-
# key-exchange mechanism.
|
19
|
-
#
|
20
|
-
# Blur does currently not support key exchanges.
|
21
|
-
class FiSH
|
22
|
-
# The standard FiSH block-size.
|
23
|
-
BlockSize = 8
|
24
|
-
|
25
|
-
# @return [String] the blowfish salt-key.
|
26
|
-
attr_accessor :keyphrase
|
27
|
-
|
28
|
-
# Change the keyphrase and instantiate a new blowfish object.
|
29
|
-
def keyphrase= keyphrase
|
30
|
-
@keyphrase = keyphrase
|
31
|
-
@blowfish = Crypt::Blowfish.new @keyphrase
|
32
|
-
end
|
33
|
-
|
34
|
-
# Instantiate a new fish-encryption object.
|
35
|
-
def initialize keyphrase
|
36
|
-
@keyphrase = keyphrase
|
37
|
-
@blowfish = Crypt::Blowfish.new keyphrase
|
38
|
-
end
|
39
|
-
|
40
|
-
# Encrypt an input string using the keyphrase stored in the +@blowfish+
|
41
|
-
# object.
|
42
|
-
#
|
43
|
-
# @return [String] the encrypted string.
|
44
|
-
def encrypt string
|
45
|
-
String.new.tap do |buffer|
|
46
|
-
nullpad(string).each_block do |block|
|
47
|
-
chunk = @blowfish.encrypt_block block
|
48
|
-
buffer.concat Base64.encode chunk
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
# Decrypt an input string using the keyphrase stored in the +@blowfish+
|
54
|
-
# object.
|
55
|
-
#
|
56
|
-
# @return [String] the decrypted string.
|
57
|
-
def decrypt string
|
58
|
-
unless string.length % 12 == 0
|
59
|
-
raise BadInputError, "input has to be a multiple of 12 characters."
|
60
|
-
end
|
61
|
-
|
62
|
-
String.new.tap do |buffer|
|
63
|
-
string.each_block 12 do |block|
|
64
|
-
chunk = @blowfish.decrypt_block Base64.decode block
|
65
|
-
buffer.concat chunk
|
66
|
-
end
|
67
|
-
end.rstrip
|
68
|
-
end
|
69
|
-
|
70
|
-
private
|
71
|
-
# Fill up the last block with null-bytes until it's a multiple of 8.
|
72
|
-
#
|
73
|
-
# @return [String] the nullpadded string.
|
74
|
-
def nullpad string
|
75
|
-
length = string.length + BlockSize - string.length % BlockSize
|
76
|
-
string.ljust length, ?\0
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
data/library/blur/encryption.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Blur
|
4
|
-
# The +Encryption+ module extends the communication-functionality of
|
5
|
-
# the client. It is intended to enable helpers but also core functionality
|
6
|
-
# that encrypts the incoming and outgoing data of Blur.
|
7
|
-
#
|
8
|
-
# Encryption modules are not loaded into the VM until it's required.
|
9
|
-
module Encryption
|
10
|
-
# Indicates that user-input (a channel user message, e.g.) is in invalid
|
11
|
-
# format to a certain encryption algorithm.
|
12
|
-
class BadInputError < StandardError; end
|
13
|
-
|
14
|
-
autoload :FiSH, "blur/encryption/fish"
|
15
|
-
autoload :Base64, "blur/encryption/base64"
|
16
|
-
end
|
17
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
# Reopens the scope of the standard Exception-class to extend it with helpful
|
4
|
-
# methods.
|
5
|
-
class Exception
|
6
|
-
# The pattern to match against the backtrace log.
|
7
|
-
Pattern = /^.*?:(\d+):/
|
8
|
-
|
9
|
-
# Retrieve the line on which the exception was raised from when raised inside
|
10
|
-
# a script.
|
11
|
-
#
|
12
|
-
# @return Fixnum the line of the script the exception was raised on.
|
13
|
-
def line
|
14
|
-
if result = backtrace[0].match(Pattern)
|
15
|
-
result[1].to_i + 1
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
# Reopens the scope of the standard String-class to extend it with helpful
|
21
|
-
# methods.
|
22
|
-
class String
|
23
|
-
# Checks if the string contains nothing but a numeric value.
|
24
|
-
#
|
25
|
-
# @return true if it is a numeric value.
|
26
|
-
def numeric?
|
27
|
-
self =~ /^\d+$/
|
28
|
-
end
|
29
|
-
|
30
|
-
# Split a string up in n chunks and then iterate through them, exactly like
|
31
|
-
# Enumerable#each_slice.
|
32
|
-
#
|
33
|
-
# @return [Enumerator] list of slices.
|
34
|
-
# @yieldreturn [Array] list of elements in each slice consecutively.
|
35
|
-
def each_slice size = 8
|
36
|
-
self.chars.each_slice(size).each{|slice| yield slice.join }
|
37
|
-
end
|
38
|
-
|
39
|
-
alias_method :starts_with?, :start_with?
|
40
|
-
alias_method :each_block, :each_slice
|
41
|
-
end
|
data/library/blur/evaluable.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Blur
|
4
|
-
module Evaluable
|
5
|
-
# Evaluate the contents of the input file in the context of +self+.
|
6
|
-
def evaluate_source_file path
|
7
|
-
instance_eval File.read(path), File.basename(path), 0
|
8
|
-
@__evaluated = true
|
9
|
-
rescue Exception => exception
|
10
|
-
puts "#{exception.message ^ :bold} on line #{exception.line.to_s ^ :bold}"
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
data/library/blur/extension.rb
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Blur
|
4
|
-
# +Extension+ provides a sort of modules for scripts, for common functionality.
|
5
|
-
#
|
6
|
-
# Think of it as a kind of scripts for scripts.
|
7
|
-
class Extension
|
8
|
-
include Evaluable
|
9
|
-
include Script::DSL
|
10
|
-
include Logging
|
11
|
-
|
12
|
-
# @return the path in which the script remains.
|
13
|
-
attr_accessor :__path
|
14
|
-
# Can be used inside the script to act with the client itself.
|
15
|
-
# @return [Network::Client] the client delegate.
|
16
|
-
attr_accessor :__client
|
17
|
-
|
18
|
-
# Instantiates a new extension context and evaluates the +path+ extension
|
19
|
-
# file.
|
20
|
-
def initialize path
|
21
|
-
@__path = path
|
22
|
-
|
23
|
-
if evaluate_source_file path
|
24
|
-
log.info "Loaded extension #{@__path}"
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
# Purely for DSL purposes.
|
29
|
-
#
|
30
|
-
# @example
|
31
|
-
# Extension :http do
|
32
|
-
# …
|
33
|
-
# end
|
34
|
-
def Extension name, &block
|
35
|
-
@__name = name
|
36
|
-
|
37
|
-
instance_eval &block
|
38
|
-
|
39
|
-
true
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,91 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Blur
|
4
|
-
class Network
|
5
|
-
# The +Channel+ class is used for encapsulating a channel and its properties.
|
6
|
-
#
|
7
|
-
# Users inside the channel is stored in the {#channels} attribute.
|
8
|
-
#
|
9
|
-
# Modes can be set for a channel, but Blur is not
|
10
|
-
# {http://www.irc.org/tech_docs/005.html ISupport}-compliant yet.
|
11
|
-
#
|
12
|
-
# @todo make so that channels *and* users belongs to the network, and not
|
13
|
-
# like now where the user belongs to the channel, resulting in multiple
|
14
|
-
# user instances.
|
15
|
-
class Channel
|
16
|
-
# @return [String] the channels name.
|
17
|
-
attr_accessor :name
|
18
|
-
# @return [Array] a list of users in the channel.
|
19
|
-
attr_accessor :users
|
20
|
-
# @return [String] the channels topic.
|
21
|
-
attr_accessor :topic
|
22
|
-
# @return [String] all the modes set on the channel.
|
23
|
-
attr_accessor :modes
|
24
|
-
# @return [Network] a reference to the network.
|
25
|
-
attr_accessor :network
|
26
|
-
# @return [Encryption::Fish] the channel encryption, if any.
|
27
|
-
attr_accessor :encryption
|
28
|
-
|
29
|
-
# Check whether or not this is an encrypted channel.
|
30
|
-
def encrypted?; not @encryption.nil? end
|
31
|
-
|
32
|
-
# Instantiate a user with a nickname, a network and a user list.
|
33
|
-
def initialize name, network = nil, users = []
|
34
|
-
@name = name
|
35
|
-
@users = users
|
36
|
-
@modes = ""
|
37
|
-
@network = network
|
38
|
-
|
39
|
-
users.each { |user| user.channel = self }
|
40
|
-
end
|
41
|
-
|
42
|
-
# Merge the channels mode corresponding to the leading character (+ or -).
|
43
|
-
#
|
44
|
-
# @param [String] modes the modes to merge with.
|
45
|
-
def merge_modes modes
|
46
|
-
addition = true
|
47
|
-
|
48
|
-
modes.each_char do |char|
|
49
|
-
case char
|
50
|
-
when ?+
|
51
|
-
addition = true
|
52
|
-
when ?-
|
53
|
-
addition = false
|
54
|
-
else
|
55
|
-
addition ? @modes.concat(char) : @modes.delete!(char)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
# Send a message to the channel.
|
61
|
-
#
|
62
|
-
# @param [String] message the message to send.
|
63
|
-
def say message
|
64
|
-
@network.say self, message
|
65
|
-
end
|
66
|
-
|
67
|
-
# Find a user with +nick+ as its nickname.
|
68
|
-
#
|
69
|
-
# @param [String] nick the nickname to find the user of.
|
70
|
-
def user_by_nick nick
|
71
|
-
@users.find { |user| user.nick == nick }
|
72
|
-
end
|
73
|
-
|
74
|
-
# Convert it to a debug-friendly format.
|
75
|
-
def inspect
|
76
|
-
%{#<#{self.class.name} @name=#{@name.inspect} @users=#{@users.inspect}}
|
77
|
-
end
|
78
|
-
|
79
|
-
# Called when YAML attempts to save the object, which happens when a
|
80
|
-
# scripts cache contains this user and the script is unloaded.
|
81
|
-
def to_yaml options = {}
|
82
|
-
@name.to_yaml options
|
83
|
-
end
|
84
|
-
|
85
|
-
# Get the channels name.
|
86
|
-
def to_s
|
87
|
-
@name
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
@@ -1,83 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Blur
|
4
|
-
class Network
|
5
|
-
# The +Command+ class is used for encapsulating the command-lines.
|
6
|
-
#
|
7
|
-
# Blur is using regular-expression for parsing, this is to be replaced
|
8
|
-
# with a more native way of parsing, making it much, much easier on the
|
9
|
-
# processor.
|
10
|
-
class Command
|
11
|
-
# @return [Symbol, Fixnum] the command name.
|
12
|
-
# @example
|
13
|
-
# 332 or :quit
|
14
|
-
attr_accessor :name
|
15
|
-
# @return [Array] a list of parameters.
|
16
|
-
attr_accessor :params
|
17
|
-
# @return [String] a hostname or a hostmask.
|
18
|
-
attr_accessor :prefix
|
19
|
-
|
20
|
-
# The arbitrary regex pattern.
|
21
|
-
Pattern = /^(?:[:@]([^\s]+) )?([^\s]+)(?: ((?:[^:\s][^\s]* ?)*))?(?: ?:(.*))?$/
|
22
|
-
|
23
|
-
# Parse a line and encapsulate it as a Command.
|
24
|
-
#
|
25
|
-
# @return [Command] the parsed command.
|
26
|
-
# @example
|
27
|
-
# Command.parse "ChanServ!ChanServ@services.uplink.io MODE #uplink +v mk"
|
28
|
-
# # => #<Blur::Network::Command … >
|
29
|
-
def self.parse data
|
30
|
-
match = data.strip.match Pattern
|
31
|
-
prefix, name, args, extra = match.captures
|
32
|
-
params = extra ? args.split << extra : args.split
|
33
|
-
|
34
|
-
new(name, params).tap do |this|
|
35
|
-
this.prefix = prefix
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
# Get a parameter by its +index+.
|
40
|
-
def [] index; @params[index] end
|
41
|
-
|
42
|
-
# Instantiate a command.
|
43
|
-
#
|
44
|
-
# @see Command.parse
|
45
|
-
def initialize name, params = []
|
46
|
-
@name, @params = name, params
|
47
|
-
end
|
48
|
-
|
49
|
-
# Get the sender of the command.
|
50
|
-
#
|
51
|
-
# @note the return value is a string if it's a hostname, and an openstruct
|
52
|
-
# with the attributes #nickname, #username and #hostname if it's a
|
53
|
-
# hostmask.
|
54
|
-
#
|
55
|
-
# @return [String, OpenStruct] the sender.
|
56
|
-
def sender
|
57
|
-
return @sender if @sender
|
58
|
-
|
59
|
-
if prefix =~ /^(\S+)!(\S+)@(\S+)$/
|
60
|
-
@sender = OpenStruct.new nickname: $1, username: $2, hostname: $3
|
61
|
-
else
|
62
|
-
@sender = prefix
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
# Convert it to an IRC-compliant line.
|
67
|
-
#
|
68
|
-
# @return [String] the command line.
|
69
|
-
def to_s
|
70
|
-
String.new.tap do |line|
|
71
|
-
line << "#{prefix} " if prefix
|
72
|
-
line << name.to_s
|
73
|
-
|
74
|
-
params.each_with_index do |param, index|
|
75
|
-
line << ' '
|
76
|
-
line << ?: if index == params.length - 1 and param =~ /[ :]/
|
77
|
-
line << param.to_s
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
@@ -1,106 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Blur
|
4
|
-
class Network
|
5
|
-
# The +User+ class is used for encapsulating a user and its properties.
|
6
|
-
#
|
7
|
-
# The user owns a reference to its parent channel.
|
8
|
-
#
|
9
|
-
# Modes can be set for a user, but Blur is not
|
10
|
-
# {http://www.irc.org/tech_docs/005.html ISupport}-compliant yet.
|
11
|
-
#
|
12
|
-
# @todo make so that channels *and* users belongs to the network, and not
|
13
|
-
# like now where the user belongs to the channel, resulting in multiple
|
14
|
-
# user instances.
|
15
|
-
class User
|
16
|
-
# @return [String] the users nickname.
|
17
|
-
attr_accessor :nick
|
18
|
-
# @return [String] the users username.
|
19
|
-
attr_accessor :name
|
20
|
-
# @return [String] the users hostname.
|
21
|
-
attr_accessor :host
|
22
|
-
# @return [String] all the modes set on the user.
|
23
|
-
attr_accessor :modes
|
24
|
-
# @return [Channel] a reference to the users channel.
|
25
|
-
attr_accessor :channel
|
26
|
-
# @return [Network] a reference to the network.
|
27
|
-
attr_accessor :network
|
28
|
-
|
29
|
-
# Check to see if the user is an admin (+a)
|
30
|
-
def admin?; @modes.include? "a" end
|
31
|
-
# Check to see if the user has voice (+v)
|
32
|
-
def voice?; @modes.include? "v" end
|
33
|
-
# Check to see if the user is the owner (+q)
|
34
|
-
def owner?; @modes.include? "q" end
|
35
|
-
# Check to see if the user is an operator (+o)
|
36
|
-
def operator?; @modes.include? "o" end
|
37
|
-
# Check to see if the user is an half-operator (+h)
|
38
|
-
def half_operator?; @modes.include? "h" end
|
39
|
-
|
40
|
-
# Instantiate a user with a nickname.
|
41
|
-
def initialize nick
|
42
|
-
@nick = nick
|
43
|
-
@modes = ""
|
44
|
-
|
45
|
-
if modes = prefix_to_mode(nick[0])
|
46
|
-
@nick = nick[1..-1]
|
47
|
-
@modes = modes
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
# Merge the users mode corresponding to the leading character (+ or -).
|
52
|
-
#
|
53
|
-
# @param [String] modes the modes to merge with.
|
54
|
-
def merge_modes modes
|
55
|
-
addition = true
|
56
|
-
|
57
|
-
modes.each_char do |char|
|
58
|
-
case char
|
59
|
-
when ?+
|
60
|
-
addition = true
|
61
|
-
when ?-
|
62
|
-
addition = false
|
63
|
-
else
|
64
|
-
addition ? @modes.concat(char) : @modes.delete!(char)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
# Send a private message to the user.
|
70
|
-
#
|
71
|
-
# @param [String] message the message to send.
|
72
|
-
def say message
|
73
|
-
@network.say self, message
|
74
|
-
end
|
75
|
-
|
76
|
-
# Convert it to a debug-friendly format.
|
77
|
-
def inspect
|
78
|
-
%{#<#{self.class.name} @nick=#{@nick.inspect} @channel=#{@channel.name.inspect}>}
|
79
|
-
end
|
80
|
-
|
81
|
-
# Called when YAML attempts to save the object, which happens when a
|
82
|
-
# scripts cache contains this user and the script is unloaded.
|
83
|
-
def to_yaml options = {}
|
84
|
-
@nick.to_yaml options
|
85
|
-
end
|
86
|
-
|
87
|
-
# Get the users nickname.
|
88
|
-
def to_s
|
89
|
-
@nick
|
90
|
-
end
|
91
|
-
|
92
|
-
private
|
93
|
-
|
94
|
-
# Translate a nickname-prefix to a mode character.
|
95
|
-
def prefix_to_mode prefix
|
96
|
-
case prefix
|
97
|
-
when '@' then 'o'
|
98
|
-
when '+' then 'v'
|
99
|
-
when '%' then 'h'
|
100
|
-
when '&' then 'a'
|
101
|
-
when '~' then 'q'
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
@@ -1,77 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Blur
|
4
|
-
class Script
|
5
|
-
# The +Cache+ class enables data storing inside Blur and it scripts.
|
6
|
-
#
|
7
|
-
# What it does is simply store a hash, and act like it is that hash.
|
8
|
-
#
|
9
|
-
# When the client closes, it sends a message to all available scripts
|
10
|
-
# and then those scripts tells the cache to save, in order to remember
|
11
|
-
# that data and reload it at the next run.
|
12
|
-
#
|
13
|
-
# Cache can then save the contents of the hash to a yaml file that persists
|
14
|
-
# in the ./cache/ directory.
|
15
|
-
#
|
16
|
-
# That same file is then loaded once needed again.
|
17
|
-
class Cache
|
18
|
-
# Get the path to the cache directory (./cache/)
|
19
|
-
def self.path
|
20
|
-
%{#{File.dirname File.expand_path $0}/cache}
|
21
|
-
end
|
22
|
-
|
23
|
-
# Check if there exists a cache file for the script with name +name+.
|
24
|
-
def self.exists? name
|
25
|
-
File.exists? "#{path}/#{name}.yml"
|
26
|
-
end
|
27
|
-
|
28
|
-
# Get a cache value by key.
|
29
|
-
def [] key; @hash[key] end
|
30
|
-
|
31
|
-
# Set a cache value by key.
|
32
|
-
def []= key, value; @hash[key] = value end
|
33
|
-
|
34
|
-
# Instantiate a cache with a script reference.
|
35
|
-
def initialize script
|
36
|
-
@hash = {}
|
37
|
-
@script = script
|
38
|
-
end
|
39
|
-
|
40
|
-
# Save all internal data to a yaml file in the cache directory.
|
41
|
-
def save
|
42
|
-
directory = File.dirname path
|
43
|
-
|
44
|
-
unless File.directory? directory
|
45
|
-
Dir.mkdir directory
|
46
|
-
end
|
47
|
-
|
48
|
-
File.open path, ?w do |file|
|
49
|
-
YAML.dump @hash, file
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
# Load a yaml file as internal data from the cache directory.
|
54
|
-
#
|
55
|
-
# @return [Hash] the loaded data.
|
56
|
-
def load
|
57
|
-
if yaml = YAML.load_file(path)
|
58
|
-
@hash = yaml
|
59
|
-
end
|
60
|
-
rescue
|
61
|
-
File.unlink path
|
62
|
-
end
|
63
|
-
|
64
|
-
# Let Hash#to_s do the job.
|
65
|
-
def to_s; @hash end
|
66
|
-
|
67
|
-
private
|
68
|
-
|
69
|
-
# The current caches file path.
|
70
|
-
#
|
71
|
-
# @return [String] the file path.
|
72
|
-
def path
|
73
|
-
%{#{Cache.path}/#{@script.__name}.yml}
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
@@ -1,77 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Blur
|
4
|
-
class Script
|
5
|
-
# The +Commands+ module is a module that gives the ability to turn a
|
6
|
-
# script into a DSL-like framework.
|
7
|
-
module Commands
|
8
|
-
class Command
|
9
|
-
DefaultOptions = { prefix: '.', hostmask: nil }
|
10
|
-
|
11
|
-
def initialize triggers, options = {}, &block
|
12
|
-
@triggers = Array === triggers ? triggers : [triggers]
|
13
|
-
@options = DefaultOptions.merge options
|
14
|
-
@block = block
|
15
|
-
end
|
16
|
-
|
17
|
-
# Called by the Commands module.
|
18
|
-
#
|
19
|
-
# Calls the command block if the trigger matches the criteria.
|
20
|
-
def received_message user, channel, message
|
21
|
-
prefix = @options[:prefix]
|
22
|
-
|
23
|
-
# Return if the prefix don't match.
|
24
|
-
return unless message.start_with? prefix
|
25
|
-
|
26
|
-
# Return if the hostmask don't match.
|
27
|
-
# FIXME: Maybe use globbing instead of regular expressions?
|
28
|
-
unless @options[:hostmask].nil?
|
29
|
-
hostmask = "#{user.nick}!#{user.name}@#{user.host}"
|
30
|
-
|
31
|
-
return unless hostmask =~ @options[:hostmask]
|
32
|
-
end
|
33
|
-
|
34
|
-
command, args = split_message message
|
35
|
-
|
36
|
-
# Strip the prefix and compare the trigger name.
|
37
|
-
if self.matches_trigger? command
|
38
|
-
@block.call user, channel, args
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
protected
|
43
|
-
|
44
|
-
def split_message message
|
45
|
-
prefix = @options[:prefix]
|
46
|
-
command, args = message[prefix.length..-1].split $;, 2
|
47
|
-
|
48
|
-
return command, args
|
49
|
-
end
|
50
|
-
|
51
|
-
def matches_trigger? command
|
52
|
-
return @triggers.find{|trigger| trigger.to_s == command }
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
# Extend +base+ with self.
|
57
|
-
def self.extended base
|
58
|
-
base.instance_variable_set :@__commands, []
|
59
|
-
end
|
60
|
-
|
61
|
-
# Add a new command handler and trigger.
|
62
|
-
def command name, *args, &block
|
63
|
-
@__commands << Command.new(name, *args, &block)
|
64
|
-
end
|
65
|
-
|
66
|
-
# Handle all calls to the scripts +message+ method, check to see if
|
67
|
-
# the message containts a valid command, serialize it and pass it to
|
68
|
-
# the script as command_name with the parameters +user+, +channel+
|
69
|
-
# and +message+.
|
70
|
-
def message user, channel, line
|
71
|
-
@__commands.each do |command|
|
72
|
-
command.received_message user, channel, line
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|