blur 1.8.6 → 2.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.
@@ -38,9 +38,9 @@ module Blur
38
38
  # Called when a line was received, the connection sends it to the network
39
39
  # delegate which then sends it to the client.
40
40
  def receive_line line
41
- command = Command.parse line
41
+ message = IRCParser::Message.parse line
42
42
 
43
- @network.got_command command
43
+ @network.got_message message
44
44
  end
45
45
 
46
46
  # Called when the SSL handshake was completed with the remote server,
@@ -1,140 +1,147 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Blur
4
- # The +Script+ class is used for encapsulating dynamically loaded ruby scripts.
5
- #
6
- # The {Script#Script} method is then used to shape the DSL-language to make
7
- # writing Blur scripts a breeze.
8
- #
9
- # @todo add examples in the documentation
10
- # @see Script#Script
11
- class Script
12
- include Logging
13
- include Evaluable
14
- include DSL
15
-
16
- ExtensionNotFoundError = Class.new StandardError
17
- Emissions = [:connection_ready, :topic_change, :user_rename, :message,
18
- :private_message, :user_entered, :user_left, :user_quit,
19
- :user_kicked, :topic, :user_mode, :channel_mode,
20
- :channel_created, :channel_who_reply]
21
-
22
- # @return the path in which the script remains.
23
- attr_accessor :__path
24
- # Can be used inside the script to act with the client itself.
25
- # @return [Network::Client] the client delegate.
26
- attr_accessor :__client
27
- # @return [Array] a list of handled emissions.
28
- attr_accessor :__emissions
29
-
30
- # A list of extensions.
31
- @@__extensions = []
32
-
33
- # Find and evaluate script extensions.
34
- def self.load_extensions!
35
- root_path = File.dirname $0
36
-
37
- Dir.glob("#{root_path}/extensions/*.rb").each do |path|
38
- extension = Extension.new path
39
- extension.__client = self
40
- extension.extension_loaded if extension.respond_to? :extension_loaded
41
-
42
- @@__extensions << extension
4
+ module Commands
5
+ # This is a command look-up-table with an autoincrementing index.
6
+ class CommandLUT
7
+ attr_accessor :commands
8
+
9
+ def initialize
10
+ @index = -1
11
+ @commands = {}
12
+ end
13
+
14
+ # Inserts the command to the LUT.
15
+ #
16
+ # @returns the index.
17
+ def << command
18
+ @commands[command] = @index += 1
19
+ @index
43
20
  end
44
21
  end
45
22
 
46
- # "Unload" all script extensions.
47
- def self.unload_extensions!
48
- @@__extensions.clear
23
+ module ClassMethods
24
+ # Creates a new command.
25
+ #
26
+ # @example
27
+ # command! '!ping' do |user, channel, args|
28
+ # channel.say "#{user}: pong"
29
+ # end
30
+ def command! command, *args, &block
31
+ id = (command_lut << command)
32
+ define_method :"_command_#{id}", &block
33
+ end
49
34
  end
50
-
51
- # Check to see if the script has been evaluated.
52
- def evaluated?; @__evaluated end
53
-
54
- # Instantiates a script and evaluates the contents which remain in +path+.
55
- def initialize path
56
- @__path = path
57
- @__evaluated = false
58
- @__emissions = []
59
-
60
- if evaluate_source_file path
61
- cache.load if Cache.exists? @__name
62
-
63
- Emissions.each do |emission|
64
- @__emissions.push emission if respond_to? emission
65
- end
66
-
67
- __send__ :loaded if respond_to? :loaded
68
- __send__ :module_init if respond_to? :module_init
35
+
36
+ def self.included klass
37
+ class << klass
38
+ attr_accessor :command_lut
69
39
  end
40
+
41
+ klass.extend ClassMethods
42
+ klass.command_lut = CommandLUT.new
43
+ klass.register! message: -> (script, user, channel, line) {
44
+ command, args = line.split ' ', 2
45
+ return unless command
46
+
47
+ if id = klass.command_lut.commands[command.downcase]
48
+ script.__send__ :"_command_#{id}", user, channel, args
49
+ end
50
+ }
70
51
  end
71
-
72
- # Make it a DSL-way of writing a script.
73
- #
74
- # @example
75
- # Script :example do
76
- # def connection_ready network
77
- # #
78
- # end
79
- # end
80
- def Script name, options = {}, &block
81
- @__name = name
82
-
83
- extensions = options[:using] || options[:uses]
84
-
85
- # Automatically used extensions.
86
- if extensions
87
- extensions.each {|extension_name| using extension_name }
52
+ end
53
+
54
+ class SuperScript
55
+ class << self
56
+ attr_accessor :name, :authors, :version, :description, :events
57
+
58
+ # Sets the author.
59
+ #
60
+ # @example
61
+ # Author 'John Doe <john.doe@example.com>'
62
+ def Author *authors
63
+ @authors = authors
88
64
  end
89
65
 
90
- # Automatically included modules.
91
- if options[:includes]
92
- options[:includes].each{|module_name| self.extend module_name }
66
+ # Sets the description.
67
+ #
68
+ # @example
69
+ # Description 'This is an example script.'
70
+ def Description description
71
+ @description = description
72
+ end
73
+
74
+ # Sets the version.
75
+ #
76
+ # @example
77
+ # Version '1.0.0'
78
+ def Version version
79
+ @version = version
93
80
  end
94
-
95
- instance_eval &block
96
-
97
- true
98
- end
99
81
 
100
- # Add script extension and define a method with the same name as
101
- # the extension.
102
- def using *extension_names
103
- extension_names.each do |extension_name|
104
- if extension = @@__extensions.find{|ext| ext.__name.to_s == extension_name.to_s }
105
- extension.extension_used self if extension.respond_to? :extension_used
106
- self.metaclass.send :define_method, :"#{extension_name}" do
107
- return extension
82
+ # Registers events to certain functions.
83
+ #
84
+ # @example
85
+ # register! message: :on_message, connection_ready: :connected
86
+ def register! *args
87
+ args.each do |events|
88
+ case events
89
+ when Hash
90
+ events.each do |event, method_name|
91
+ register_event! event, method_name
92
+ end
93
+ when Array
94
+ register! *events
95
+ when Symbol
96
+ register_event! events
108
97
  end
109
- else
110
- raise ExtensionNotFoundError, "Extension not found: #{extension_name}"
111
98
  end
112
99
  end
113
- end
114
-
115
- # Unload the script and save the cache, if present.
116
- def unload!
117
- cache.save if @__cache
118
- __send__ :unloaded if respond_to? :unloaded
119
100
 
120
- @__cache = nil
121
- end
101
+ # Adds the given event +name+ and the name of the method to call once the
102
+ # event is emitted.
103
+ def register_event! name, method_name = name
104
+ (@events[name] ||= []) << method_name
105
+ end
122
106
 
123
- # Access another script with name +name+.
124
- #
125
- # @return [Script] the script with the name +name+, or nil.
126
- def script name
127
- @__client.scripts.find { |script| script.__name == name }
128
- end
129
-
130
- # Get the cache, if none, instantiate a new cache.
131
- def cache
132
- @__cache ||= Cache.new self
107
+ def to_s; inspect end
108
+ def inspect; %%#<SuperScript:0x#{self.object_id.to_s 16}>% end
109
+
110
+ alias :author :authors
111
+ alias :Authors :Author
133
112
  end
134
-
135
- # Convert it to a debug-friendly format.
113
+
114
+ # Called when when the superscript has been loaded and added to the list of
115
+ # superscripts.
116
+ def self.init; end
117
+
118
+ # Called right before the script is being removed from the list of
119
+ # superscripts.
120
+ def self.deinit; end
121
+
122
+ # Reference to the main client that holds the script.
123
+ attr_accessor :_client_ref
124
+
125
+ # Script-specific configuration that is read from the main configuration
126
+ # file.
127
+ attr_accessor :config
128
+
129
+ attr_accessor :cache
130
+
131
+ # Called right before the instance of the script is being removed.
132
+ def unloaded; end
133
+
134
+ # Gets the instantiated script with +name+.
135
+ def script name; _client_ref.scripts[name] end
136
+
137
+ # Gets a human-readable representation of the script.
136
138
  def inspect
137
- File.basename @__path
139
+ "#<Script(#{self.class.name.inspect}) " \
140
+ "@author=#{self.class.author.inspect} " \
141
+ "@version=#{self.class.version.inspect} " \
142
+ "@description=#{self.class.description.inspect}>"
138
143
  end
144
+
145
+ def to_s; inspect end
139
146
  end
140
147
  end
@@ -0,0 +1,43 @@
1
+ # encoding: utf-8
2
+
3
+ module Blur
4
+ class ScriptCache < Hash
5
+ def initialize script_name, path, hash
6
+ @script_name = script_name
7
+ @path = path
8
+ @hash = hash
9
+ end
10
+
11
+ # Gets a cache +value+ by its +key+.
12
+ def [] key; @hash[key] end
13
+
14
+ # Sets the cache +key+ to the provided +value+.
15
+ def []= key, value; @hash[key] = value end
16
+
17
+ # Saves the cache as a YAML file.
18
+ def save
19
+ directory = File.dirname @path
20
+
21
+ unless File.directory? directory
22
+ Dir.mkdir directory
23
+ end
24
+
25
+ File.open @path, ?w do |file|
26
+ YAML.dump @hash, file
27
+ end
28
+ end
29
+
30
+ # Loads the cache file for +script_name+ in +cache_dir+ if it exists.
31
+ def self.load script_name, cache_dir
32
+ cache_path = File.join cache_dir, "#{script_name}.yml"
33
+
34
+ if File.exists? cache_path
35
+ object = YAML.load_file cache_path
36
+
37
+ ScriptCache.new script_name, cache_path, object
38
+ else
39
+ ScriptCache.new script_name, cache_path, {}
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,105 @@
1
+ # encoding: utf-8
2
+
3
+ module Blur
4
+ # The +User+ class is used for encapsulating a user and its properties.
5
+ #
6
+ # The user owns a reference to its parent channel.
7
+ #
8
+ # Modes can be set for a user, but Blur is not
9
+ # {http://www.irc.org/tech_docs/005.html ISupport}-compliant yet.
10
+ #
11
+ # @todo make so that channels *and* users belongs to the network, and not
12
+ # like now where the user belongs to the channel, resulting in multiple
13
+ # user instances.
14
+ class User
15
+ # @return [String] the users nickname.
16
+ attr_accessor :nick
17
+ # @return [String] the users username.
18
+ attr_accessor :name
19
+ # @return [String] the users hostname.
20
+ attr_accessor :host
21
+ # @return [String] all the modes set on the user.
22
+ attr_accessor :modes
23
+ # @return [Network] a reference to the network.
24
+ attr_accessor :network
25
+ attr_accessor :channels
26
+
27
+ # Check to see if the user is an admin (+a)
28
+ def admin?; @modes.include? "a" end
29
+ # Check to see if the user has voice (+v)
30
+ def voice?; @modes.include? "v" end
31
+ # Check to see if the user is the owner (+q)
32
+ def owner?; @modes.include? "q" end
33
+ # Check to see if the user is an operator (+o)
34
+ def operator?; @modes.include? "o" end
35
+ # Check to see if the user is an half-operator (+h)
36
+ def half_operator?; @modes.include? "h" end
37
+
38
+ # Instantiate a user with a nickname.
39
+ def initialize nick, network = nil
40
+ @nick = nick
41
+ @modes = String.new
42
+ @channels = []
43
+ @network = network
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}:0x#{self.object_id.to_s 16} @nick=#{@nick.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
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Blur
4
4
  # The current version of Blur.
5
- Version = "1.8.6"
5
+ Version = "2.1"
6
6
 
7
7
  # Get the current version.
8
8
  #
metadata CHANGED
@@ -1,71 +1,67 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blur
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.6
4
+ version: '2.1'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mikkel Kroman
8
8
  autorequire:
9
- bindir: bin
9
+ bindir: executables
10
10
  cert_chain: []
11
- date: 2016-01-11 00:00:00.000000000 Z
11
+ date: 2017-09-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: majic
14
+ name: deep_merge
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.4'
19
+ version: '1.1'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.4'
26
+ version: '1.1'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: eventmachine
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.0'
33
+ version: '1.2'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '1.0'
40
+ version: '1.2'
41
41
  description:
42
42
  email: mk@uplink.io
43
- executables: []
43
+ executables:
44
+ - blur
44
45
  extensions: []
45
46
  extra_rdoc_files: []
46
47
  files:
47
48
  - ".yardopts"
48
49
  - LICENSE
49
50
  - README.md
51
+ - executables/blur
50
52
  - library/blur.rb
53
+ - library/blur/callbacks.rb
54
+ - library/blur/channel.rb
51
55
  - library/blur/client.rb
52
- - library/blur/encryption.rb
53
- - library/blur/encryption/base64.rb
54
- - library/blur/encryption/fish.rb
55
56
  - library/blur/enhancements.rb
56
- - library/blur/evaluable.rb
57
- - library/blur/extension.rb
58
57
  - library/blur/handling.rb
58
+ - library/blur/logging.rb
59
59
  - library/blur/network.rb
60
- - library/blur/network/channel.rb
61
- - library/blur/network/command.rb
62
60
  - library/blur/network/connection.rb
63
61
  - library/blur/network/isupport.rb
64
- - library/blur/network/user.rb
65
62
  - library/blur/script.rb
66
- - library/blur/script/cache.rb
67
- - library/blur/script/commands.rb
68
- - library/blur/script/dsl.rb
63
+ - library/blur/script_cache.rb
64
+ - library/blur/user.rb
69
65
  - library/blur/version.rb
70
66
  homepage: https://github.com/mkroman/blur
71
67
  licenses:
@@ -87,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
87
83
  version: '0'
88
84
  requirements: []
89
85
  rubyforge_project:
90
- rubygems_version: 2.2.0
86
+ rubygems_version: 2.6.13
91
87
  signing_key:
92
88
  specification_version: 4
93
89
  summary: An event-driven IRC-framework for Ruby.