blur 1.8.6 → 2.1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,140 +1,156 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
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: lambda { |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
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
106
+
107
+ def to_s
108
+ inspect
109
+ end
110
+
111
+ def inspect
112
+ %(#<SuperScript:0x#{object_id.to_s 16}>)
113
+ end
114
+
115
+ alias author authors
116
+ alias Authors Author
121
117
  end
122
118
 
123
- # Access another script with name +name+.
124
- #
125
- # @return [Script] the script with the name +name+, or nil.
119
+ # Called when when the superscript has been loaded and added to the list of
120
+ # superscripts.
121
+ def self.init; end
122
+
123
+ # Called right before the script is being removed from the list of
124
+ # superscripts.
125
+ def self.deinit; end
126
+
127
+ # Reference to the main client that holds the script.
128
+ attr_accessor :_client_ref
129
+
130
+ # Script-specific configuration that is read from the main configuration
131
+ # file.
132
+ attr_accessor :config
133
+
134
+ attr_accessor :cache
135
+
136
+ # Called right before the instance of the script is being removed.
137
+ def unloaded; end
138
+
139
+ # Gets the instantiated script with +name+.
126
140
  def script name
127
- @__client.scripts.find { |script| script.__name == name }
141
+ _client_ref.scripts[name]
128
142
  end
129
-
130
- # Get the cache, if none, instantiate a new cache.
131
- def cache
132
- @__cache ||= Cache.new self
133
- end
134
-
135
- # Convert it to a debug-friendly format.
143
+
144
+ # Gets a human-readable representation of the script.
136
145
  def inspect
137
- File.basename @__path
146
+ "#<Script(#{self.class.name.inspect}) " \
147
+ "@author=#{self.class.author.inspect} " \
148
+ "@version=#{self.class.version.inspect} " \
149
+ "@description=#{self.class.description.inspect}>"
150
+ end
151
+
152
+ def to_s
153
+ inspect
138
154
  end
139
155
  end
140
156
  end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blur
4
+ class ScriptCache
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
13
+ @hash[key]
14
+ end
15
+
16
+ # Sets the cache +key+ to the provided +value+.
17
+ def []= key, value
18
+ @hash[key] = value
19
+ end
20
+
21
+ # Saves the cache as a YAML file.
22
+ def save
23
+ directory = File.dirname @path
24
+
25
+ Dir.mkdir directory unless File.directory? directory
26
+
27
+ File.open @path, 'w' do |file|
28
+ YAML.dump @hash, file
29
+ end
30
+ end
31
+
32
+ # Loads the cache file for +script_name+ in +cache_dir+ if it exists.
33
+ def self.load script_name, cache_dir
34
+ cache_path = File.join cache_dir, "#{script_name}.yml"
35
+
36
+ if File.exist? cache_path
37
+ object = YAML.load_file cache_path
38
+
39
+ ScriptCache.new script_name, cache_path, object
40
+ else
41
+ ScriptCache.new script_name, cache_path, {}
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
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
+ # @return [Hash<String, String>] a map of symbols to channel user modes.
28
+ COMMON_SYMBOL_MODES = {
29
+ '@' => 'o',
30
+ '+' => 'v',
31
+ '%' => 'h',
32
+ '&' => 'a',
33
+ '~' => 'q'
34
+ }.freeze
35
+
36
+ # Check to see if the user is an admin (+a)
37
+ def admin?
38
+ @modes.include? 'a'
39
+ end
40
+
41
+ # Check to see if the user has voice (+v)
42
+ def voice?
43
+ @modes.include? 'v'
44
+ end
45
+
46
+ # Check to see if the user is the owner (+q)
47
+ def owner?
48
+ @modes.include? 'q'
49
+ end
50
+
51
+ # Check to see if the user is an operator (+o)
52
+ def operator?
53
+ @modes.include? 'o'
54
+ end
55
+
56
+ # Check to see if the user is an half-operator (+h)
57
+ def half_operator?
58
+ @modes.include? 'h'
59
+ end
60
+
61
+ # Instantiate a user with a nickname.
62
+ def initialize nick, network = nil
63
+ @nick = nick
64
+ @modes = String.new
65
+ @channels = []
66
+ @network = network
67
+
68
+ return unless (modes = prefix_to_mode(nick[0]))
69
+
70
+ @nick = nick[1..]
71
+ @modes = modes
72
+ end
73
+
74
+ # Merge the users mode corresponding to the leading character (+ or -).
75
+ #
76
+ # @param [String] modes the modes to merge with.
77
+ def merge_modes modes
78
+ addition = true
79
+
80
+ modes.each_char do |char|
81
+ case char
82
+ when '+'
83
+ addition = true
84
+ when '-'
85
+ addition = false
86
+ else
87
+ addition ? @modes.concat(char) : @modes.delete!(char)
88
+ end
89
+ end
90
+ end
91
+
92
+ # Send a private message to the user.
93
+ #
94
+ # @param [String] message the message to send.
95
+ def say message
96
+ @network.say self, message
97
+ end
98
+
99
+ # Convert it to a debug-friendly format.
100
+ def inspect
101
+ %(#<#{self.class.name}:0x#{object_id.to_s 16} @nick=#{@nick.inspect}>)
102
+ end
103
+
104
+ # Called when YAML attempts to save the object, which happens when a
105
+ # scripts cache contains this user and the script is unloaded.
106
+ def to_yaml options = {}
107
+ @nick.to_yaml options
108
+ end
109
+
110
+ # Get the users nickname.
111
+ def to_s
112
+ @nick
113
+ end
114
+
115
+ private
116
+
117
+ # Translate a nickname-prefix to a mode character.
118
+ def prefix_to_mode prefix
119
+ COMMON_SYMBOL_MODES[prefix]
120
+ end
121
+ end
122
+ end
@@ -1,13 +1,13 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Blur
4
4
  # The current version of Blur.
5
- Version = "1.8.6"
5
+ VERSION = '2.1.6'
6
6
 
7
7
  # Get the current version.
8
8
  #
9
9
  # @return [String] The current version of Blur.
10
10
  def self.version
11
- Version
11
+ VERSION
12
12
  end
13
13
  end
data/library/blur.rb CHANGED
@@ -1,36 +1,63 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
- require 'pp'
4
3
  require 'yaml'
5
- require 'majic'
6
4
  require 'socket'
5
+ require 'base64'
7
6
  require 'ostruct'
8
7
  require 'openssl'
8
+
9
+ require 'deep_merge/rails_compat'
9
10
  require 'eventmachine'
11
+ require 'ircparser'
10
12
 
11
13
  # Require all library files.
12
- require 'blur/version'
13
- require 'blur/client'
14
- require 'blur/evaluable'
15
- require 'blur/script/dsl'
16
- require 'blur/extension'
17
- require 'blur/script'
18
- require 'blur/network'
19
- require 'blur/encryption'
20
- require 'blur/enhancements'
21
- require 'blur/script/cache'
22
- require 'blur/network/user'
23
- require 'blur/network/channel'
24
- require 'blur/network/command'
25
- require 'blur/network/isupport'
26
- require 'blur/network/connection'
27
- require 'blur/script/commands'
14
+ require_relative './blur/version'
15
+ require_relative './blur/callbacks'
16
+ require_relative './blur/script'
17
+ require_relative './blur/script_cache'
18
+ require_relative './blur/network'
19
+ require_relative './blur/client'
20
+ require_relative './blur/user'
21
+ require_relative './blur/channel'
22
+ require_relative './blur/network/isupport'
23
+ require_relative './blur/network/connection'
28
24
 
29
25
  # Blur is a very modular IRC-framework for ruby.
30
26
  #
31
27
  # It allows the developer to extend it in multiple ways.
32
28
  # It can be by handlers, scripts, communications, and what have you.
33
29
  module Blur
30
+ # Client error.
31
+ class ClientError < StandardError; end
32
+
33
+ # Configuration file error.
34
+ class ConfigError < StandardError; end
35
+
36
+ # Creates a new superscript class and inserts it into the list of scripts.
37
+ def self.Script name, *_args, &block
38
+ klass = Class.new SuperScript
39
+ klass.name = name
40
+ klass.events = {}
41
+ klass.class_exec &block
42
+ klass.init
43
+
44
+ scripts[name] = klass
45
+ end
46
+
47
+ # Gets all superscript classes.
48
+ def self.scripts
49
+ @scripts ||= {}
50
+ end
51
+
52
+ # Resets all scripts.
53
+ #
54
+ # This method will call `deinit` on each script class before removing them to
55
+ # give them a chance to clean up.
56
+ def self.reset_scripts!
57
+ scripts.each_value &:deinit
58
+ scripts.clear
59
+ end
60
+
34
61
  # Instantiates a client with given options and then makes the client instance
35
62
  # evaluate the given block to form a DSL.
36
63
  #
metadata CHANGED
@@ -1,77 +1,85 @@
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.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mikkel Kroman
8
- autorequire:
9
- bindir: bin
8
+ autorequire:
9
+ bindir: executables
10
10
  cert_chain: []
11
- date: 2016-01-11 00:00:00.000000000 Z
11
+ date: 2021-12-14 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.2'
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.2'
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'
41
- description:
40
+ version: '1.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: ircparser
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.6'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.6'
55
+ description:
42
56
  email: mk@uplink.io
43
- executables: []
57
+ executables:
58
+ - blur
44
59
  extensions: []
45
60
  extra_rdoc_files: []
46
61
  files:
47
62
  - ".yardopts"
48
63
  - LICENSE
49
64
  - README.md
65
+ - executables/blur
50
66
  - library/blur.rb
67
+ - library/blur/callbacks.rb
68
+ - library/blur/channel.rb
51
69
  - library/blur/client.rb
52
- - library/blur/encryption.rb
53
- - library/blur/encryption/base64.rb
54
- - library/blur/encryption/fish.rb
55
- - library/blur/enhancements.rb
56
- - library/blur/evaluable.rb
57
- - library/blur/extension.rb
58
70
  - library/blur/handling.rb
59
71
  - library/blur/network.rb
60
- - library/blur/network/channel.rb
61
- - library/blur/network/command.rb
62
72
  - library/blur/network/connection.rb
63
73
  - library/blur/network/isupport.rb
64
- - library/blur/network/user.rb
65
74
  - library/blur/script.rb
66
- - library/blur/script/cache.rb
67
- - library/blur/script/commands.rb
68
- - library/blur/script/dsl.rb
75
+ - library/blur/script_cache.rb
76
+ - library/blur/user.rb
69
77
  - library/blur/version.rb
70
78
  homepage: https://github.com/mkroman/blur
71
79
  licenses:
72
80
  - MIT
73
81
  metadata: {}
74
- post_install_message:
82
+ post_install_message:
75
83
  rdoc_options: []
76
84
  require_paths:
77
85
  - library
@@ -79,16 +87,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
79
87
  requirements:
80
88
  - - ">="
81
89
  - !ruby/object:Gem::Version
82
- version: 1.9.1
90
+ version: '2.7'
83
91
  required_rubygems_version: !ruby/object:Gem::Requirement
84
92
  requirements:
85
93
  - - ">="
86
94
  - !ruby/object:Gem::Version
87
95
  version: '0'
88
96
  requirements: []
89
- rubyforge_project:
90
- rubygems_version: 2.2.0
91
- signing_key:
97
+ rubygems_version: 3.1.4
98
+ signing_key:
92
99
  specification_version: 4
93
100
  summary: An event-driven IRC-framework for Ruby.
94
101
  test_files: []