Class: GodObject::Smuxi::Plugin

Inherits:
Object
  • Object
show all
Defined in:
lib/god_object/smuxi/plugin.rb

Overview

Note:

This class is supposed to be an abstract base class and is not meant to produce instances directly.

Base class that implements basic features of a Smuxi plugin.

Constant Summary collapse

BASE_DIRECTORY_NAME =
'smuxi'
HOOKS_DIRECTORY_NAME =
'hooks'
STATE_DIRECTORY_NAME =
'hook-state'
STATE_FILE_NAME =
'state.yml'
HOOK_TABLE =
{
  'engine/protocol-manager/on-connected'        => :connected,
  'engine/protocol-manager/on-disconnected'     => :disconnected,
  'engine/protocol-manager/on-message-received' => :message_received,
  'engine/protocol-manager/on-message-sent'     => :message_sent,
  'engine/protocol-manager/on-presence-status-changed' => :presence_status_changed,
  'engine/session/on-group-chat-person-added'   => :chat_person_added,
  'engine/session/on-group-chat-person-removed' => :chat_person_removed,
  'engine/session/on-group-chat-person-updated' => :chat_person_updated,
  'engine/session/on-event-message'             => :event_message 
}
VARIABLE_TABLE =
{
  'SMUXI_CHAT_ID'   => :@chat_id,
  'SMUXI_CHAT_NAME' => :@chat_name,
  'SMUXI_CHAT_TYPE' => :@chat_type,
  'SMUXI_MSG'                     => :@message,
  'SMUXI_MSG_TYPE'                => :@message_type,
  'SMUXI_MSG_TIMESTAMP_UNIX'      => :@message_timestamp_unix,
  'SMUXI_MSG_TIMESTAMP_ISO_UTC'   => :@message_timestamp_iso_utc,
  'SMUXI_MSG_TIMESTAMP_ISO_LOCAL' => :@message_timestamp_iso_local,
  'SMUXI_SENDER'   => :@sender,
  'SMUXI_RECEIVER' => :@receiver,
  'SMUXI_PROTOCOL_MANAGER_TYPE'            => :@protocol_manager_type,
  'SMUXI_PROTOCOL_MANAGER_PROTOCOL'        => :@protocol_manager_protocol,
  'SMUXI_PROTOCOL_MANAGER_NETWORK'         => :@protocol_manager_network,
  'SMUXI_PROTOCOL_MANAGER_HOST'            => :@protocol_manager_host,
  'SMUXI_PROTOCOL_MANAGER_PORT'            => :@protocol_manager_port,
  'SMUXI_PROTOCOL_MANAGER_ME_ID'           => :@protocol_manager_me_id,
  'SMUXI_PROTOCOL_MANAGER_PRESENCE_STATUS' => :@protocol_manager_presence_status,
  'SMUXI_PRESENCE_STATUS_CHANGED_OLD_STATUS'  => :@presence_status_old,
  'SMUXI_PRESENCE_STATUS_CHANGED_NEW_STATUS'  => :@presence_status_new,
  'SMUXI_PRESENCE_STATUS_CHANGED_NEW_MESSAGE' => :@presence_status_new_message,
  'SMUXI_CMD'              => :@command,
  'SMUXI_CMD_PARAMETER'    => :@command_parameter,
  'SMUXI_CMD_CHARACTER'    => :@command_character,
  'SMUXI_FRONTEND_VERSION' => :@frontend_version,
  'SMUXI_ENGINE_VERSION'   => :@engine_version 
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Plugin

Initializes the plugin.

Known variables' values from the supplied environment will be transferred to the respective instance variables.

Options Hash (options):

  • environment ({String => String})

    environment variables for the plugin execution

  • base_directory (Pathname)

    the configuration directory for Smuxi. The hooks and hook-state sub-directories are expected to reside here

  • state_directory (Pathname)

    the directory that Smuxi reserved for this plugin to store its state.

  • hook_name (String)

    name of the Smuxi hook that is executed

  • script_name (String)

    name of plugin hook executable, without path

See Also:


304
305
306
307
308
309
310
311
312
313
314
315
316
# File 'lib/god_object/smuxi/plugin.rb', line 304

def initialize(options = {})
  @environment     = options[:environment]
  @base_directory  = options[:base_directory]
  @state_directory = options[:state_directory]
  @state           = options[:state]
  @hook_name       = options[:hook_name]
  @script_name     = options[:script_name]

  VARIABLE_TABLE.each do |environment_variable, instance_variable|
    instance_variable_set(instance_variable,
                          @environment[environment_variable])
  end
end

Instance Attribute Details

#stateObject (readonly)

Returns the value of attribute state


286
287
288
# File 'lib/god_object/smuxi/plugin.rb', line 286

def state
  @state
end

Class Method Details

.base_directory_guessPathname


214
215
216
# File 'lib/god_object/smuxi/plugin.rb', line 214

def base_directory_guess
  Pathname.new('~/.local/share').expand_path + BASE_DIRECTORY_NAME
end

.cli_install(executable_path) ⇒ void

Note:

This method outputs to STDOUT and exits the program after it finishes.

This method returns an undefined value.

Installs the plugin by placing symlinks to the plugin executable into Smuxi's hook handler paths.


177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/god_object/smuxi/plugin.rb', line 177

def cli_install(executable_path)
  puts "Creating symlinks at the Smuxi plugin hook locations…"
  puts

  install(executable_path) do |hook_executable_file|
    puts "Creating `#{hook_executable_file}`"
  end

  puts
  puts "Plugin `#{name}` installed."

  exit
end

.cli_uninstall(executable_path) ⇒ void

Note:

This method outputs to STDOUT and exits the program after it finishes.

This method returns an undefined value.

Uninstalls the plugin by removing symlinks to the plugin executable from Smuxi's hook handler paths.


199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/god_object/smuxi/plugin.rb', line 199

def cli_uninstall(executable_path)
  puts "Trying to remove hook symlinks…"
  puts
  
  uninstall(executable_path) do |hook_executable_file|
    puts "Removing `#{hook_executable_file}`"
  end

  puts
  puts "Plugin `#{name}` uninstalled."

  exit
end

.execute(executable_path, environment = ENV, arguments = ARGV) ⇒ void

This method returns an undefined value.

Decides whether to execute a plugin hook handler or plugin maintenance features.

In case the first command line argument is install or uninstall, the plugin installation or uninstallation maintenance methods are executed.

Otherwise, the plugin expects to be called as a hook handler by Smuxi.


107
108
109
110
111
112
113
114
115
116
# File 'lib/god_object/smuxi/plugin.rb', line 107

def execute(executable_path, environment = ENV, arguments = ARGV)
  case arguments.first
  when 'install'
    cli_install(executable_path)
  when 'uninstall'
    cli_uninstall(executable_path)
  else
    execute_hook(executable_path, environment)
  end
end

.execute_hook(executable_path, environment = ENV) ⇒ void

This method returns an undefined value.

The name of the hook executed is detected through the name of the executable called. A plugin instance will be created and the hook name is then used to decide which instance method is called on that.


126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/god_object/smuxi/plugin.rb', line 126

def execute_hook(executable_path, environment = ENV)
  split_pattern = /\/#{BASE_DIRECTORY_NAME}\/#{HOOKS_DIRECTORY_NAME}\//
  config_directory, relative_executable = executable_path.
                                          split(split_pattern)

  base_directory      = Pathname.new(config_directory) +
                        BASE_DIRECTORY_NAME
  relative_executable = Pathname.new(relative_executable)
  script_name         = relative_executable.basename.to_s
  hook_name           = relative_executable.dirname.to_s
  state_directory     = base_directory +
                        STATE_DIRECTORY_NAME +
                        hook_name +
                        script_name

  state_file = state_directory + STATE_FILE_NAME

  if state_file.exist?
    state = YAML.load(state_file.read)
  else
    state = {}
  end

  instance = new(
    environment:     environment,
    base_directory:  base_directory,
    script_name:     script_name,
    hook_name:       hook_name,
    state_directory: state_directory,
    state:           state
  )

  if method_name = HOOK_TABLE[hook_name]
    instance.public_send(method_name)

    state_file.open('w') do |io|
      io.write(YAML.dump(instance.state))
    end
  else
    raise "Hook `#{hook_name}` unsupported"
  end
end

.install(executable_path, base_directory = base_directory_guess, &block) ⇒ void

This method returns an undefined value.

Installs the plugin by placing symlinks to the plugin executable into Smuxi's hook handler paths.


253
254
255
256
257
258
259
260
261
262
263
# File 'lib/god_object/smuxi/plugin.rb', line 253

def install(executable_path, base_directory = base_directory_guess, &block)
  executable_file = Pathname.new(executable_path).expand_path
  executable_name = executable_file.basename.to_s

  used_hook_paths(base_directory).each do |hook_path|
    hook_executable_file = hook_path + executable_name 
    block.call(hook_executable_file) if block
    hook_executable_file.unlink if hook_executable_file.symlink?
    hook_executable_file.make_symlink(executable_file)
  end
end

.uninstall(executable_path, base_directory = base_directory_guess) {|hook_executable| ... } ⇒ void

This method returns an undefined value.

Uninstalls the plugin by removing symlinks to the plugin executable from Smuxi's hook handler paths.

Yields:

  • (hook_executable)

    hook_executable


273
274
275
276
277
278
279
280
281
282
# File 'lib/god_object/smuxi/plugin.rb', line 273

def uninstall(executable_path, base_directory = base_directory_guess, &block)
  executable_file = Pathname.new(executable_path).expand_path
  executable_name = executable_file.basename.to_s

  used_hook_paths(base_directory).each do |hook_path|
    hook_executable_file = hook_path + executable_name
    block.call(hook_executable_file) if block
    hook_executable_file.unlink if hook_executable_file.symlink?
  end
end

.used_hook_methodsArray<Symbol>


220
221
222
# File 'lib/god_object/smuxi/plugin.rb', line 220

def used_hook_methods
  instance_methods.to_set.intersection(HOOK_TABLE.values.to_set)
end

.used_hook_namesArray<String>


226
227
228
229
230
231
232
# File 'lib/god_object/smuxi/plugin.rb', line 226

def used_hook_names
  inverted_hook_table = HOOK_TABLE.invert

  used_hook_methods.map do |method_name|
    inverted_hook_table[method_name]
  end
end

.used_hook_paths(base_directory = base_directory_guess) ⇒ Array<String>


238
239
240
241
242
243
244
# File 'lib/god_object/smuxi/plugin.rb', line 238

def used_hook_paths(base_directory = base_directory_guess)
  hooks_directory = base_directory + HOOKS_DIRECTORY_NAME
  
  used_hook_names.map do |hook_name|
    hooks_directory + hook_name
  end
end

Instance Method Details

#command(type, name, data = nil) ⇒ void

This method returns an undefined value.

Calls a command in Smuxi


324
325
326
327
328
329
# File 'lib/god_object/smuxi/plugin.rb', line 324

def command(type, name, data = nil)
  command = "#{type} /#{name}"
  command += " #{data}" if data
  
  STDOUT.puts(command)
end

#protocol_manager_command(name, data = nil) ⇒ void

This method returns an undefined value.

Calls a protocol manager command in Smuxi


345
346
347
# File 'lib/god_object/smuxi/plugin.rb', line 345

def protocol_manager_command(name, data = nil)
  command('ProtocolManager.Command', name, data)
end

#puts(message) ⇒ Object

Outputs a message to the Smuxi user


352
353
354
# File 'lib/god_object/smuxi/plugin.rb', line 352

def puts(message)
  session_command(:echo, message)
end

#session_command(name, data = nil) ⇒ void

This method returns an undefined value.

Calls a session command in Smuxi


336
337
338
# File 'lib/god_object/smuxi/plugin.rb', line 336

def session_command(name, data = nil)
  command('Session.Command', name, data)
end